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

时间:2016-11-26 18:26:05

标签: c++ inheritance polymorphism object-slicing

我对C ++中的子类有些怀疑。我有这段代码:

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

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

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

BaseClass foo = SubClass();

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

foo.doSomething();

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

foo.SubClass::doSomething();

有没有办法做到这一点,或者我被迫用“SubClass”类型声明对象以使其使用自己的函数?

3 个答案:

答案 0 :(得分:2)

Use virtual and override:

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

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

edit: as Christophe said, use a virtual destructor as above.

答案 1 :(得分:1)

问题1:对象切片

在初始化

BaseClass foo = SubClass();

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

这称为object slicing。如果baseClass具有数据成员,则子类的相应数据成员将被复制到其中。如果SubClass有其他数据成员,则会丢失这些成员。

如果你想使用BaseClass个对象,但没有丢失它们真实类型的成员,无论是base还是派生,你需要使用引用或指针:

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。在这种情况下,编译器将生成具有一点开销的代码,能够动态识别对象的类型,因此将完全按照您的预期调用函数的正确版本。

请注意,如果基类中至少有一个虚函数,则最好为其声明虚拟析构函数。

答案 2 :(得分:0)

You can declare the dosomeThing method virtual in BaseClass, like

virtual void doSomething()
{
   ----
}