То, что вы пытаетесь сделать, невозможно в C ++. Переменные в C ++ имеют фиксированный тип, который определяется во время компиляции, и они не могут изменять тип во время выполнения. Но C ++ обеспечивает полиморфизм (который выглядит как динамические типы), который позволяет производным типам реализовывать функциональность базового класса, но единственный способ получить доступ к методам, специфичным для типа, - это привязать тип к базовому классу, если у вас есть тип, связанный с производный тип, то вы можете вызвать только реализацию этого типа *:
class Base
{
public: virtual void Func () = 0;
};
class C1 : public Base
{
public: virtual void Func () {}
};
class C2 : public Base
{
public: virtual void Func () {}
};
void SomeFunc ()
{
C1 *c1 = new C1;
C2 *c2 = new C2;
Base *b;
b = c1;
b->Func (); // calls C1::Func
b = c2;
b->Func (); // calls C2::Func
}
Похоже, b
изменил тип, но его фактический тип остался прежним, это всегда Base *
, и ему можно присвоить только значения c1
и c2
, потому что они имеют общую базу класс Base
. Можно пойти другим путем:
Base *b = new C1;
C1 *c1 = dynamic_cast <C1 *> (b);
, но для этого требуется dynamic_cast
, а для этого требуется нечто, называемое RTTI (информация о типе времени выполнения), которое предоставляет скомпилированному коду способ проверить, что b
действительно указывает на тип C1
. Если вы должны были сделать следующее:
Base *b = new C2;
C1 *c1 = dynamic_cast <C1 *> (b);
c1
будет нулевым указателем, а не b
. Но C1 и C2 все еще должны иметь общий базовый класс, чтобы это работало. Это не законно:
class Base {....}
class C1 : public Base {....}
class C2 {....} // not derived from Base!
Base *b = new C2; // no way to convert C2 to Base!
C2 *c2 = new C2;
b = dynamic_cast <Base *> (c2); // still won't work, C2 not a Base
b = new C1; // fine, C1 is a Base
C1 *c1 = new C1;
b = c1; // again, fine
c1 = dynamic_cast <C1 *> (b); // fine, C1 is a derived type of Base, this will work
c2 = dynamic_cast <C2 *> (b); // won't work, C2 is not a derived type of Base
Если C1 и C2 связаны (скажем, CSquare и CCircle), то общий базовый класс имеет смысл. Если они не связаны (скажем, CRoad и CFood), то общий базовый класс не поможет (это можно сделать, но это не очень логично). Выполнение первого (общий базовый класс) было хорошо описано в других ответах. Если вам нужно сделать последнее, то вам может понадобиться переосмыслить, как структурирован код, чтобы позволить вам сделать первое.
Было бы полезно, если бы вы могли расширить то, что вы хотите сделать с x
. Поскольку x
является контейнером, вы просто хотите выполнить операции, связанные с контейнером?
- Конечно, в C ++ никогда не бывает так просто, и есть много вещей, которые могут запутать проблему. Например, производный тип может реализовать виртуальный метод общедоступного базового класса в частном порядке:
* +1034 * Пример: * * одна тысяча тридцать пять
class B
{
public:
virtual void F () = 0;
};
class C : public B
{
private:
virtual void F () { .... }
};
C *c = new C;
B *b = c;
b->F (); // OK
c->F (); // error