问题描述
我有四个不同的C ++类。 Comp()
,其中包含Parent()
,其中有两个孩子ChildA()
和ChildB()
。我想根据某些参数在ChildA
内动态创建ChildB
或Comp()
的实例。
我的代码看起来像这样:
class Parent {
public:
foo();
};
class ChildA : public Parent {
public:
foo(); // Overrides Parent.foo()
};
class ChildB : public Parent {
public:
foo(); // Overrides Parent.foo()
};
class Comp {
public:
Init(uint8_t someParam){
if(someParam){
obj = new ChildA();
}
else{
obj = new ChildB();
}
}
doFoo(){
obj->foo();
}
private:
Parent* obj;
};
但是,这不能编译。这使我犯了链接器错误,提示我对Parent::foo()
/build/libComp.a(Comp.cpp.o): In function `Comp::doFoo()':
Comp.cpp:(.text._ZN6Memory8readByteEt+0x4e): undefined reference to `Parent::foo()'
我觉得这里缺少基本的东西。我来自Python编程的背景,所以我还没有完全将思维过程切换到C ++。我可以这样使用类吗?
解决方法
当您是一名Python程序员时,您已经习惯了每种方法都是虚拟方法的世界,而重载意味着您只需替换dict中的值即可。 C ++有所不同。
因此,第一个解决方案是定义Parent::foo
方法。您已经声明了它,该类不是模板-因此必须在某个位置定义主体。无论如何,调用obj->foo();
都无济于事,意味着调用Parent::foo()
方法,我想那不是您想要的。
现在我们进入虚拟方法的世界:在C ++中,您必须显式声明一个方法为virtual
:
class Parent {
public:
virtual foo();
};
您仍然需要在某处定义Parent::foo()
的正文。
如果您不想通过设计来定义它,则可以使此方法抽象(因此,类Parent
也变成了抽象,并且该类的任何实例都不能已创建):
class Parent {
public:
virtual foo() = 0;
};
您无需将派生类的方法foo
声明为虚拟方法(无论如何它们都将是虚拟的),但是最佳实践是添加override
或final
说明符:
class ChildA : public Parent {
public:
foo() final; // Overrides Parent.foo()
};
class ChildB : public Parent {
public:
foo() override; // Overrides Parent.foo()
};
区别在于您无法为ClassA
覆盖此方法,而可以为ClassB
进行此操作。