我对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”类型声明对象以使其使用自己的函数?
答案 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()
{
----
}