C ++对动态创建的类成员的功能的未定义引用

问题描述

我有四个不同的C ++类。 Comp(),其中包含Parent(),其中有两个孩子ChildA()ChildB()。我想根据某些参数在ChildA内动态创建ChildBComp()的实例。

我的代码看起来像这样:

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声明为虚拟方法(无论如何它们都将是虚拟的),但是最佳实践是添加overridefinal说明符:

class ChildA : public Parent {
  public:
    foo() final; // Overrides Parent.foo()
};

class ChildB : public Parent {
  public:
    foo() override; // Overrides Parent.foo()
};

区别在于您无法为ClassA覆盖此方法,而可以为ClassB进行此操作。