强制 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,你最好为它声明一个虚析构函数。
我对 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,你最好为它声明一个虚析构函数。