C++的抽象类继承和构造函数的问题
Problem with abstract class inheritance and constructor at C++
class Base {
public:
Base(int a) : a_(a) {
//do something
someMethod();
//do something else
};
protected:
int a_;
virtual void someMethod() = 0 {};
};
class Derived : Base {
public:
Derived() {
Base::Base(42);
}
protected:
void someMethod() override {
//realisation
}
};
int main() {
Derived *obj = new Derived();
delete obj;
}
此代码由于两个错误而不起作用:需要基类的默认构造函数,并且由于使用抽象方法而无法调用带有参数的基类构造函数
我的问题是,当我创建class Derived
对象时,根本不调用class Derived
中实现someMethod()
。我也不想使用class Base
的默认构造函数,但编译器是发誓的。
如何更正代码以查看所需的功能?
如何更正我的代码以查看我想要的功能?
-
删除
Base
构造函数中对纯虚函数的调用。 -
在重写它的派生类的构造函数中调用
someMethod
。 -
为成员初始器列表中的
Base
子对象提供初始化器。如果不向基提供初始化器,它将默认初始化。
为什么这行不通?
由于构造方式,此设计将不起作用。
当你构造一个Derived
时,首先发生的是Base
对象是用Base
构造函数构造的。目前没有Derived
对象,因此,如果要在Base
构造函数中调用虚拟函数,则在离开Base
构造函数的主体之前,对Base
类有效的将是虚拟函数。
这是标准允许的,但有限制:
[base.class.init]/16:可以为正在构造的对象调用成员函数(包括虚拟成员函数(。(...)然而 如果这些操作是在 CTOR 初始值设定项(或 函数直接或间接从 ctor-初始值设定项调用(之前 基类的所有 MEM 初始值设定项都已完成,程序 具有未定义的行为。
这些限制不适用于从构造函数主体调用的虚函数,因为主体在所有初始值设定项之后执行。
但在您的情况下,虚拟函数对于Base
来说是纯虚拟的。 所以根据以下条款,它是UB:
[class.abstract]/6:成员函数可以从抽象类的构造函数(或析构函数(调用;使 直接对纯虚函数进行虚拟调用,或 间接地为从这样的对象创建(或销毁( 构造函数(或析构函数(未定义。
什么是替代方案
不幸的是,除了使用两步初始化之外,没有其他真正的替代方法,在两步初始化中,您首先构造对象,然后在使用对象之前调用初始化函数。
此方法的唯一问题是忘记调用初始化函数的风险。 您可以保护您免受以下影响:
- 使用标志来指示是否已发生初始化,并在所有成员函数中检查此标志(是的,它有点开销(。
- 如果你有一个抽象类,你可以使用工厂模式(工厂方法或抽象工厂(。然后,您可以让工厂进行呼叫。 您可以使用构建器
- 模式,并确保构造函数仅对不会忘记初始化的构建器可见。
代码的其他问题
您必须小心如何从派生构造函数"调用"基构造函数:
class Derived : Base {
public:
Derived() : Base(42) // this is the correct place !
{
//Base::Base(42); //<==== OUCH !!! NO !! This creates a temporary base object !!
}
...
};
您还需要注意纯虚拟(我不知道这是错别字还是您的编译器可以编译您的代码(:
virtual void someMethod() = 0; // if it's abstract, no pending {} !
- 变分模板递归构造函数问题
- C++重载构造函数问题
- 迷宫构造函数问题 [线程 1:EXC_BAD_ACCESS(代码 = 1,地址 = 0x8)]
- 构造函数问题<无法读取内存>
- 构造函数问题
- 另一个类中的类的构造函数问题
- 类构造函数问题
- 遇到构造函数问题
- C++ STM32用户定义的类构造函数问题
- 模板嵌套类的构造函数问题(复制 ctor 似乎覆盖了其他 ctor)
- 布尔构造函数问题的动态数组
- C++ 构造函数问题 // 继承的类
- C++:构造函数问题
- 类没有复制构造函数问题
- C++重载构造函数问题
- C++构造函数问题
- 在我的程序中"无符号"之前的预期主表达式(析构函数和构造函数问题)
- 复制构造函数问题C++:"0xC0000005: Access violation writing location 0x00000000."
- c++成员函数和构造函数问题
- c++派生类构造函数问题