Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 默认析构函数的gcc异常规范_C++_Linux_Exception_Gcc_Throw - Fatal编程技术网

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

C++ 默认析构函数的gcc异常规范,c++,linux,exception,gcc,throw,C++,Linux,Exception,Gcc,Throw,该代码给出以下错误: 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; } 在我的debian测试(gcc(debian 4.6.0-10)4.6.1 20

该代码给出以下错误:

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;
}
在我的debian测试(gcc(debian 4.6.0-10)4.6.1 20110526(预发布))中,但在以前的gcc版本(再次在我的debian系统上为4.5)中编译时没有错误


根据这个答案,编译器应该创建一个与基类的抛出声明相匹配的默认构造函数。显然,这不是新gcc的情况。改变了什么,正确的编译器行为是什么,除了在派生类中手动添加空析构函数(例如编译器标志)之外,是否有一些简单的解决方案。

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

按照我的理解,如果类B有一个析构函数,它显式地不抛出任何东西(即

应该没问题

不管怎样,上次我检查时,从d'tors抛出异常是非常糟糕的做法


希望这能对你有所帮助!

我假设在真实代码中,
~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()

这是实际的代码吗?如果跳过成员声明,则可能会更改结果。此外,您是否指定了C++11支持?规则在wrt析构函数中稍有更改,虽然代码应该仍然正常,但可能在某个地方有错误。不,这不是实际的代码。我可以确定,因为它至少有一个语法错误。@Yordan,提问时请发布实际的、可编译的代码。有关如何做到这一点以及为什么它很重要的详细信息,请参阅。@Rob-O.O你一定是在开玩笑吧….?这不是一个复杂而长的源代码的问题,这些东西很重要。缺少两个明显的分号,这不会改变问题,信息,环境,任何东西。@Kiril:我100%同意Rob。如果OP在发布的代码中引入了新的错误,我们怎么能期望在原始代码中找到错误?在这种情况下,一个完整的、可编译的示例是非常重要的,因为如果他向派生类添加了一个成员,并且为了简单起见删除了该成员,那么无论该错误是否是他的错误或编译器的可以更改。目前,该错误是一个编译器错误。声明异常规范也是一个糟糕的做法“除了在派生类中手动添加空析构函数外,是否有其他简单的解决方案”。还添加了
throw()
(注意-这是空throw说明符(类似于C++0x中的
nothrow
)的析构函数不同于仅仅使用抛出说明符。这不是一个坏的做法。甚至建议这样做-析构函数不应该抛出,对吗?(:我不确定这是否可能..但据我所知,事情不应该被扔出d'tors。这意味着每次你在try/catch中删除一个对象时都必须进行包装。我会说:不-但这在我看来像是滥用了抛出机制,所以我不能肯定当你以一种相反的方式滥用它时会发生什么o,在从C++规范读取了OP帖子的摘录之后,没有指定基类重写函数的相同异常类型的方法。我想这与指针类型的模糊有关。谢谢你的回答。(我现在在示例中更正了这一点)。看起来在您提供的解决方案中,将throw()添加到A是适合我的解决方案。更好的解决方案是根本不使用
throw
规范。现在,该规范被广泛视为语言中的错误。
error: looser throw specifier for ‘virtual C::~C()’
error:   overriding ‘virtual B::~B() throw ()’
class B: public A
{
public:
virtual ~B() throw { }
}