强制派生的类对象使用自己的功能,而不是基类功能

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

本文关键字:功能 基类 自己的 派生 对象      更新时间:2023-10-16

我对C 中的子类有一些疑问。我有此代码:

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

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

BaseClass foo = SubClass();

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

foo.doSomething();

它使用父类方法而不是派生的方法。我尝试了这个,但它不起作用:

foo.SubClass::doSomething();

有什么方法可以做到这一点,或者我被迫用"子类"类型声明对象,以使其使用自己的函数?

问题1:对象切片

在您的初始化中

BaseClass foo = SubClass();

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

这称为对象切片。如果baseClass将具有数据成员,则将复制该子类的相应数据成员。如果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

但是,这还不够。

问题2:多态性

如果您现在调用该方法:

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

尽管对象的真实类型指向/引用了对象的实际类型,但仍将被称为BaseClass::doSomething()。这是因为对于正常的成员函数,编译器试图在编译时识别要调用的功能:在编译时,它只知道指针或参考的类型。

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

请注意,如果您的基类中至少具有一个虚拟功能,则最好为其声明虚拟驱动器。

使用虚拟和覆盖:

class BaseClass() {
    BaseClass();
    virtual ~BaseClass() = default;
    virtual void doSomething();
}
class SubClass : public BaseClass {
    SubClass();
    void doSomething() override ;
}

编辑:正如克里斯托夫所说的那样,使用上述虚拟破坏者。

您可以在

中声明dosomeThing方法虚拟
virtual void doSomething()
{
   ----
}