Это основной концептуальный вопрос. Если у меня есть производный класс, наследуемый от Base, и я создаю экземпляр нового производного объекта, могу ли я установить его базовый объект на конкретный базовый объект по своему выбору, чтобы все вызовы методов базового класса перенаправлялись на этот конкретный базовый объект?
что-то вроде этого:
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;
}
Я уверен, что сделал множество ошибок в этом простом коде, потому что мой уровень навыков низок, но только для идеи.
Возможно ли это в С++? Мы можем отделить производную информацию от объекта, поэтому можем ли мы разделить и заменить компоненты в цепочке наследования?
Зачем мне это делать?
Рассмотрим миксиновые лилии: (опять же, простите за синтаксические ошибки)
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);
В этом случае, если бы мы могли установить базовый объект миксина на любой желаемый объект, мы могли бы использовать конструкторы с любым списком параметров в нашем миксине, при этом миксину не нужно было бы ничего об этом знать. Кроме того, миксин можно использовать как декоратор без необходимости использования общего интерфейса среди декораторов.
Спасибо за ответы. Поскольку мы можем отрезать производную часть объекта, кажется, что базовая и производная информация живут отдельно. Может ли кто-нибудь прокомментировать это? Можем ли мы получить доступ к какой-то внутренней таблице, такой как виртуальные таблицы, о которых я так много слышал (я ничего не знаю об этом типе вещей, так что, возможно, это неприменимо), и выполнить это?
@Бенуа
Не могли бы вы объяснить, почему работают только 1 и 4, а 2 и 3 нет? class Base { protected: std::string name; общественность: 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";
это напечатает:
оригинал 1 х = 5 новый 1 х = 6
исходное 2 х = 5 исходное 2 х = 6
Исходное 3 х = 5 Исходное 3 х = 6
исходный 4 х = 5 новый 4 х = 6
Почему это работает только при использовании указателя?