设置派生对象的基础对象? [英] set the base object of derived object?

查看:50
本文介绍了设置派生对象的基础对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个基本概念问题.如果我有一个从 Base 继承的 Derived 类,并且我实例化了一个新的 Derived 对象,我是否可以将它的 Base 对象设置为我选择的特定 Base 对象,以便所有调用基类方法都重定向到这个特定的基类对象?

This is a basic concept question. If I have a class that Derived that inherits from Base, and I instantiate a new Derived object, can I set it's Base object to a specific Base object of my choosing so that all calls base class methods are redirected to this particular base object?

像这样:

class Base
{
protected:
    string name;
public:
    Base(string n) { name = n}
    void doSomething(){cout << name << "\n";}
};

class Derived : public Base
{
public:
     Derived(string n) : Base(n) {}

int main()
{
    Derived* d = new Derived("original base"); //create a derived
    d->doSomething(); // prints "original base"
    Base* rB = new Base("replacement base"); // create a new base object
    ((Base*) d) = rB; // replace the base object of d with a new one (pretend code)
    d->doSomething(); // prints "replacement base"

    return 0;
}

我确信我在那个简单的代码中犯了各种各样的错误,因为我的技能水平很低,但只是为了这个想法.

I'm sure I made all sorts of errors in that simple code, because my skill level is low, but just for the idea.

这在 C++ 中可行吗?我们可以从一个对象中切出派生的信息,那么我们是否可以分离和替换继承链中的组件?

Is this possible in C++? We can slice the derived information off of an object, so can we separate and replace the components in a chain of inheritance?

我为什么要这样做?

考虑 mixin lilies:(再次原谅语法错误)

Consider the mixin lilies: (again, forgive syntax errors)

template <class T> class MyMixin : public T
{
public:
    MyMixin(T desiredBaseObject)
    { 
        // do something to set the desired base 
        // object of this class to desiredBaseObject.
    }
};

RandomClass1 dog(int i = 0);  
RandomClass2 cat(double i = 0.0);
MyMixin< RandomClass1 > mixin1(dog);
MyMixin< RandomClass2 > mixin2(cat);

在这种情况下,如果我们可以将 mixin 的基础对象设置为任何想要的对象,我们就可以在我们的 mixin 中使用带有任何参数列表的构造函数,而无需 mixin 需要知道任何关于它的信息.此外,mixin 可以像装饰器一样使用,而无需装饰器之间的通用接口.

In this case, if we could set the base object of the mixin to any desired object, we could use constructors with any parameter list in our mixin without the mixin needing to know anything about it. Also, the mixin could be used like a decorator without the need for a common interface amongst decorators.

感谢您的回答.由于我们可以切掉对象的派生部分,因此基本信息和派生信息似乎是分开的.有人可以对此发表评论吗?我们能不能访问一些内部表,比如我经常听到的 vtables(我对这类东西一无所知,所以这可能不适用),并完成这个?

Thanks for the answers. Since we can slice off the derived part of an object, it seems like the base and derived information lives separately. Could someone comment on this? Could we access some internal table, like the vtables I hear so much about (I don't know anything about this type of stuff, so maybe this is not applicable), and accomplish this?

@Benoit

你能解释一下为什么只有 1 和 4 可以工作,而 2 和 3 不行吗?班级基地{受保护:std::string 名称;上市:基础(标准::: 字符串 n){名称 = n;}

Could you explain why only 1 and 4 work, but 2 and 3 do not? class Base { protected: std::string name; public: Base(std::string n) { name = n; }

    virtual void doSomething()
    {
        cout << name << "\n";
    }
};

class Derived : public Base
{
public:
    int x;
    Derived(std::string n) : Base(n)
    {
        x = 5;
    }

    void printX()
    {
        cout << "x = " << x << "\n";
        x++;
    }
};


Derived* d1 = new Derived("original 1");
d1->doSomething();
d1->printX();
Base* rb1 = new Base("new 1");
*static_cast<Base*>(d1) = *rb1;
d1->doSomething();
d1->printX();
cout << "\n\n";

Derived d2 = Derived("original 2");
d2.doSomething();
d2.printX();
Base b2 = Base("new 2");
static_cast<Base>(d2) = b2;
d2.doSomething();
d2.printX();
cout << "\n\n";

Derived d3("original 3");
d3.doSomething();
d3.printX();
Base b3("new 3");
static_cast<Base>(d3) = b3;
d3.doSomething();
d3.printX();
cout << "\n\n";

Derived d4("original 4");
d4.doSomething();
d4.printX();
Base b4("new 4");
*static_cast<Base*>(&d4) = *&b4;
d4.doSomething();
d4.printX();
cout << "\n\n";

这将打印:

原1x = 5新 1x = 6

original 1 x = 5 new 1 x = 6

原2x = 5原2x = 6

original 2 x = 5 original 2 x = 6

原3x = 5原3x = 6

original 3 x = 5 original 3 x = 6

原4x = 5新 4x = 6

original 4 x = 5 new 4 x = 6

为什么这只在使用指针时有效?

Why does this only work with when using a pointer?

推荐答案

我不是在质疑您为什么要这样做,但是这样做是完全安全的,除非您的继承破坏了 ISA 关系(例如 Derived 是Base,例如 Square 不是 Rectangle,因为可以只调整 Rectangle 的一个维度的大小,而 Square 则不能这样做).

I'm not questioning why you want to do this, but it's perfectly safe do it unless your inheritance breaks the ISA relationship (eg Derived is a restricted subset of Base, eg a Square is not a Rectangle since it is possible to resize only one dimension of a Rectangle but impossible to do so with a Square).

*static_cast<Base*>(d) = *rB;

(也适用于参考文献)

或者你可以写一个小函数(你会发现有很多函数这样做):

or you can write a little function (you will find lots of functions doing this):

template<typename T>
T& assign(T& to, const T& from)
{
  return to = from;
}

assign<Base>(*d, *rB);

无论如何,每次重载/重新定义 operator= 时都要这样做

and anyway, you do this every time you overload/redefine operator=

Derived& operator=(const Derived& other)
{
  // prettier than the cast notation
  Base::operator=(other);

  // do something specific to Derived;
  this->name += " (assigned)";

  return *this;
}

这篇关于设置派生对象的基础对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆