默认析构函数的 gcc 异常规范

2024-04-16

class A
{
    public:
    virtual ~A()
    {
    }
};

class B : virtual public A
{
    public:
    ~B() throw()
    {}
};

class C : public B
{
};

int main(int argc, char * argv [])
{
return 0;
}

该代码给出以下错误:

error: looser throw specifier for ‘virtual C::~C()’
error:   overriding ‘virtual B::~B() throw ()’

在我的 debian 测试中( gcc (Debian 4.6.0-10) 4.6.1 20110526 (prerelease) ),但在以前的 gcc 版本上编译没有错误(再次在我的 debian 系统上为 4.5)。

异常规范如何影响虚拟析构函数重写? https://stackoverflow.com/questions/3233078/how-does-an-exception-specification-affect-virtual-destructor-overriding根据该答案,编译器应该创建一个与基类的 throw 声明相匹配的默认构造函数。显然这不是新 gcc 上发生的情况。发生了什么变化,正确的编译器行为是什么,除了在派生类中手动添加空析构函数(例如编译器标志)之外,是否有一些简单的解决方案可以解决该问题。


我认为在真正的代码中~A() or ~B()被声明为虚拟的? (错误消息抱怨虚拟析构函数,但在编写的代码中没有一个析构函数是虚拟的。)

我相信虚拟继承是引发您问题的原因。 C的(隐式定义的)析构函数需要首先调用~B()然后,因为 C 是最派生的类,所以调用~A()。 (12.4/6)

生成的异常规范~C()需要允许任何异常传播,因为它直接调用~A()没有例外规范。 (15.4/13)

然后就会触发你的错误 - 你不能用throw()规范(B 的析构函数)的版本可能会抛出异常。 (15.4/3)

解决方案是把throw()在 A 的析构函数上。 (如果你做不到,那你为什么要在 B 上做呢?)

如果没有虚拟继承,该错误也不会发生 - 因为这样 C 的析构函数只会调用 B 的析构函数。 (B 的析构函数仍然会调用 A 的析构函数 - 而且你仍然如履薄冰,因为如果 A 的析构函数抛出,你将直接terminate().)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

默认析构函数的 gcc 异常规范 的相关文章

随机推荐