纯虚函数调用有趣的案例

Edu*_*yan 5 c++ inheritance virtual-functions compilation pure-virtual

请考虑以下代码:

#include <iostream>
using namespace std;

class A
{
  public:
   virtual void f() = 0;
   A(){f();}
};

void A::f() {
    cout<<"A"<<endl;
}

class B:public A{
 public:
    void f(){cout<<"B"<<endl;}
};
int main()
{
 B b;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我直接从构造函数中调用虚函数并获取编译器警告,其中显示:
warning:abstract virtual'virtual void A :: f()'从构造函数调用.
但它执行时没有终止并打印A.

如果我像这样包装函数的调用:

class A
{
  public:
   virtual void f() = 0;
   A(){g();}
   void g(){f();}
};

void A::f(){cout<<"A"<<endl;}

class B:public A{
 public:
    void f(){cout<<"B"<<endl;}
};
int main()
{
 B b;
}
Run Code Online (Sandbox Code Playgroud)

编译器在编译期间不会输出任何警告,但会在运行时使用以下消息进行压缩:

pure virtual method called   
terminate called without active exception   
Abort
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释这两种情况的行为吗?

Pio*_*cki 1

\n

\xc2\xa7 10.4 抽象类 [class.abstract] / p6

\n

可以从抽象类的构造函数(或析构函数)调用成员函数;对于从这样的构造函数(或析构函数)创建(或销毁)的对象,直接或间接地对纯虚函数进行虚拟调用(10.3)的效​​果是未定义的

\n
\n

简而言之:对于从构造函数创建的对象直接或间接调用纯虚函数的效果是未定义的。

\n

无论调用是直接还是间接,都不能从构造函数或析构函数中使用对纯虚拟成员函数的调用,因为这样您最终会得到未定义的行为

\n

提供纯虚函数实现的唯一有用示例是从派生类调用它时:

\n
struct A\n{\n    virtual void f() = 0;\n};\n\nvoid A::f()\n{\n    cout<<"A"<<endl;\n}\n\nstruct B : A\n{\n    void f()\n    {\n        A::f();\n        cout<<"B"<<endl;\n    }\n};\n
Run Code Online (Sandbox Code Playgroud)\n