2 在构造函数中调用纯虚函数会出错

2 Calling pure virtual function in constructor gives an error?

本文关键字:函数 出错 调用 构造函数      更新时间:2023-10-16
class A{
public:
A(){
this->draw();
}
  virtual void draw()=0;
};

是否会导致编译错误。如果是,为什么。如果不是,为什么?

首先,从构造函数调用纯虚拟是未定义的行为。

C++11 §10.4/6:

"制作 对正在创建(或销毁(的对象直接或间接的纯虚函数进行虚拟调用 (10.3( 从这样的构造函数(或析构函数(是未定义的。

那么你的问题是,一般来说,UB是否需要诊断。

它没有。

虽然注释不是规范性的,但 C++11 §1.3.24 中的以下注释澄清了:

"允许的未定义行为 范围从完全忽略情况并产生不可预测的结果,到翻译过程中的行为或 以记录环境特征的方式执行程序(有或没有发布 诊断消息(">

使用您选择的特定选项的编译器可能会也可能不会发出诊断,然后可能会也可能不会生成可执行文件。如果是这样,构造函数的执行可能会导致也可能不会导致某些运行时错误。简而言之,这是未定义的行为。


为什么调用是未定义的行为?例如,为什么它不能调用派生类中的实现?

好吧,如果可以的话,那么派生类中的代码可以在派生类实例初始化之前执行,这意味着它可以在对实例变量值的错误假设下执行,这意味着它很容易导致错误。

这就是Java和C#中的情况。

但是,在C++中,类T的构造函数或析构函数中的代码执行是使用动态类型T*this对象执行的。此处对虚函数的调用与对象最初实例化为 T 具有相同的效果(即使T具有纯虚函数(。这确保了代码的效果与派生类中可能执行的操作无关,作为T程序员,您真正知道手头有什么。

有了这些更安全的类型规则,就不能有任何纯虚函数的派生类实现,因为在此上下文中,没有对象的派生类部分:它纯粹是一个T对象。

是的,它会导致错误。

纯虚函数

用于使类抽象,这意味着从该类继承的任何类都必须实现您的虚函数。

例如,假设你有一个从你的类 A 继承的类 B,你必须在那里实现 draw(( 方法,你可以在那里调用它。但是你永远不会在定义它的类中调用纯虚函数。