【问题标题】:2 Calling pure virtual function in constructor gives an error? [duplicate]2 在构造函数中调用纯虚函数会报错? [复制]
【发布时间】:2014-04-09 00:05:42
【问题描述】:
class A{
public:
A(){
this->draw();
}
  virtual void draw()=0;
};

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

【问题讨论】:

  • 你没有编译器来试试这个吗?如果是,你为什么不这样做?如果没有,为什么没有编译器?
  • 永远不要在构造函数和析构函数中调用虚函数。
  • @cbel:你的建议对 Java 和 C# 很有用,比如说。但是,在 C++ 中,此类调用(非纯虚函数)是安全的。这是 C++ 比上述语言更安全的罕见情况之一。

标签: c++


【解决方案1】:

首先,构造函数中对纯虚的调用是Undefined Behavior。

C++11 §10.4/6:

“制作的效果 为正在创建(或销毁)的对象直接或间接地对纯虚函数进行虚拟调用(10.3) 来自这样的构造函数(或析构函数)是未定义的。”

那么您的问题是,一般情况下,UB 是否需要诊断。

没有。

虽然注释不是规范,但来自 C++11 §1.3.24 的以下注释阐明了:

“允许的未定义行为 范围从完全无视情况导致不可预测的结果,到在翻译或 以环境特征的文件化方式执行程序(有或没有发布 诊断信息)”

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


为什么是调用Undefined Behavior?例如,为什么它不能在派生类中调用实现?

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

这就是例如的情况。 Java 和 C#。

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

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

【讨论】:

    【解决方案2】:

    是的,它会导致错误。

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

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

    【讨论】:

      猜你喜欢
      • 2013-01-27
      • 2012-01-28
      • 2021-10-20
      • 2012-01-27
      • 1970-01-01
      • 2012-01-28
      • 2013-02-18
      相关资源
      最近更新 更多