众所周知,我们可以使用纯虚拟析构函数,如下所示:
struct A {
virtual ~A() = 0;
};
A::~A() {}
struct B : A {};
因为标准在10.4 [class.abstract] p2
只有在调用...(12.4 [class.dtor])
时才需要定义纯虚函数
后来在12.4 [class.dtor] p9
析构函数可以声明为虚拟(10.3)或纯虚拟(10.4);如果在程序中创建了该类或任何派生类的任何对象,则应定义析构函数。
上述代码完全有效意味着什么 - A::~A
可能是纯虚拟的,已定义,B::~B
隐式调用A::~A
。
到目前为止,非常好
然后我读了10.4 [class.abstract] p6
:
可以从抽象类的构造函数(或析构函数)调用成员函数;对于从这样的构造函数(或析构函数)创建(或销毁)的对象,直接或间接地对纯虚函数进行虚拟调用(10.3)的效果是未定义的。
但这正是我们在这里所做的 - 我们从析构函数中调用纯虚函数A::~A
。
那么,是不是存在某种矛盾?
答案 0 :(得分:3)
没有收缩。
您从A
的析构函数调用B
的虚拟析构函数。A
析构函数不是B
的成员。
标准§9.3
会员职能
在类的定义中声明的函数,不包括那些 用朋友说明者宣布( 11.3),被称为该类的成员函数
标准声明当从抽象类析构函数/构造函数(在您的情况下,将为类A
)中的虚拟调用到其中一个时,存在未定义的行为拥有纯虚拟成员函数。
[...]可以从抽象类[...]的构造函数(或析构函数)调用成员函数;
你的引言是针对析构函数的:
答案 1 :(得分:-2)
如果存在虚拟呼叫(10.3 [class.virtual]),则会发生UB。
对纯虚函数进行虚拟调用(10.3)的效果是未定义的。
但10.3 [class.virtual] p15表示
使用范围运算符(5.1)进行显式限定可以抑制虚拟调用机制。
似乎隐式析构函数调用具有明确的限定条件 至少编译器肯定不会在那里进行虚拟调用。