强制 derived-class 对象使用它自己的函数,而不是 base-class 对象

Force a derived-class object to use its own function, not the base-class one

我对 C++ 中的 subclasses 有一些疑问。我有这个代码:

class BaseClass() {
    BaseClass();
    void doSomething();
}

class SubClass : public BaseClass {
    SubClass();
    void doSomething();
}

当我声明一个可能是子类的 BaseClass 对象时,我会调用子构造函数...

BaseClass foo = SubClass();

然后我需要 foo 来使用派生的 doSomething() 方法 class,但是当我这样做时...

foo.doSomething();

它使用父 class 方法而不是派生方法。我试过这个,但它不起作用:

foo.SubClass::doSomething();

有什么方法可以做到吗,或者我不得不用 "SubClass" 类型声明对象以使其使用自己的功能?

您可以在 BaseClass 中声明 dosomeThing 方法为虚方法,例如

virtual void doSomething()
{
   ----
}

使用虚拟并覆盖:

class BaseClass() {
    BaseClass();
    virtual ~BaseClass() = default;
    virtual void doSomething();
}

class SubClass : public BaseClass {
    SubClass();
    void doSomething() override ;
}

编辑:正如 Christophe 所说,使用上面的虚拟析构函数。

问题一:对象切片

在你的初始化中

BaseClass foo = SubClass();

您创建了一个匿名临时 SubClass 对象并复制构造了一个 BaseClass 对象。这意味着 foo 是并且仍然是从 SubClass 复制的 BaseClass

这叫做object slicing。如果 baseClass 有数据成员,则 subclass 的相应数据成员将被复制到其中。如果 SubClass 有额外的数据成员,这些将丢失。

如果你想使用 BaseClass 对象,但又不丢失其真实类型的成员,无论是基类还是派生类,你需要使用引用或指针:

BaseClass *foo = new SubClass;  // foo is a base class pointer but points to a SubClass object. 

SubClass bar;  
BaseClass& foo2 = bar;          // foo2 is a base class REFERENCE which refers to a Subclass object

但是,这还不够。

问题二:多态性

如果您现在调用方法:

foo->doSomething();  
foo2.doSomething(); 

它仍然会被调用 BaseClass::doSomething(),尽管 pointed/referred 对象的真实类型。这是因为对于普通成员函数,编译器会尝试在编译时识别要调用的函数:并且在编译时它只知道指针或引用的类型。

要从多态行为中获益,您还需要将函数定义为 virtual,如 所述。在这种情况下,编译器生成的代码只需少量开销就能够动态识别对象的类型,因此可以完全按照您的预期调用函数的正确版本。

注意如果你的基类中至少有一个虚函数class,你最好为它声明一个虚析构函数。