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

发布于 2024-11-18 02:07:20 字数 770 浏览 4 评论 0原文

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)。

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

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;
}

That code gives the following error:

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

on my debian testing ( gcc (Debian 4.6.0-10) 4.6.1 20110526 (prerelease) ) but compiles without errors on previous gcc versions ( 4.5 on my debian system again).

How does an exception specification affect virtual destructor overriding?
According to that answer the compiler is supposed to create a default constructor matching the throw declaration of the base class. Obviously this is not what happens on new gcc. What has changed, what is the correct compiler behavior and is there some easy solution to the problem other than manually adding empty destructors in derived classes ( compiler flag for example).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽手叙旧 2024-11-25 02:07:21

我认为在实际代码中 ~A()~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()。)

I presume that in the real code either ~A() or ~B() is declared virtual? (The error message is complaining about a virtual destructor, but in the code as written none of the destructors are virtual.)

I believe the virtual inheritance is what is triggering your problem. C's (implicitly defined) destructor is required to first call ~B() and then, because C is the most-derived class, to call ~A(). (12.4/6)

The generated exception specification for ~C() is required to allow any exception to propagate, because it directly calls ~A() which has no exception specification. (15.4/13)

And that then triggers your error - you can't override a virtual function with a throw() specification (B's destructor) with a version that may throw. (15.4/3)

The solution would be to put throw() on A's destructor. (If you can't do that, then why are you doing it on B's?)

The error also wouldn't happen without the virtual inheritance - because then C's destructor would only call B's destructor. (B's destructor would still call A's - and you're still skating on thin ice, because if A's destructor throws you're going straight to terminate().)

谜泪 2024-11-25 02:07:21

GCC 4.X 比以前的版本更严格,因此可能不会隐式声明。尝试明确说明。

按照我的理解,如果 B 类有一个显式抛出任何内容的析构函数(即,

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

应该没问题。

无论如何,上次我检查从 d'tors 抛出异常是非常糟糕的做法。

希望对您有所帮助!

GCC 4.X is stricter than previous versions, and therefore may not state it implicitly. Try stating it explicitly.

The way I understand it, if class B had a destructor which explicitly threw nothing (ie.

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

It should be ok.

Regardless, last time I checked it was very poor practice to throw exceptions from d'tors.

Hope that helps ya some!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文