什么c ++标准说关于在默认析构函数中丢失throw specifier [英] What the c++ standard says about loosing throw specifier in default destructor

查看:232
本文介绍了什么c ++标准说关于在默认析构函数中丢失throw specifier的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

三个不同的编译器显示了编译此代码的三种不同行为:

  class MyException:public std :: exception 
{
public:
MyException(std :: string str):m_str(str){}
virtual const char * what()const throw(){return m_str.c_str }
protected:
std :: string m_str;
};

Sun C ++ 5.8补丁121017-22 2010/09/29:警告函数MyException ::〜MyException()只能抛出由函数std :: exception ::〜exception()抛出的异常



g ++ 3.4.3: Visual Studio 2005:非常高兴 错误 looser throw说明符为`virtual MyException ::〜MyException >(无错误或警告)

 类别异常{
public:
exception ;
exception(const exception&)throw();
exception& operator =(const exception&)throw();
virtual〜exception()throw();
virtual const char * what()const throw();
}

我知道问题是什么,以及如何解决它:

  class MyException:public std :: exception 
{
public:
MyException str):m_str(str){}
virtual const char * what()const throw(){return m_str.c_str(); }
〜MyException()throw(){}< ------------现在就好了!
protected:
std :: string m_str;
};

但我想知道标准在具体情况下说。 p>

我在Visual Studio 2005中运行了另一个小测试,我发现了真的让我吃惊的东西:

  struct Base 
{
virtual int foo()const throw(){return 5; }
};

struct派生:public Base
{
int foo()const {return 6; }
};

int main()
{
Base * b = new Derived;
std :: cout<< b-> foo()<< std :: endl; //< - this line print 6!
delete b;
}

两个函数的签名不同。这如何工作?看起来visual studio 2005完全忽略了异常规范。

  struct Base 
{
virtual int foo ()const throw(){return 5; }
};

struct派生:public Base
{
int foo(){return 6; } //我删除了const关键字
//并且签名已更改
};

int main()
{
基本* b = new Derived;
std :: cout<< b-> foo()<< std :: endl; //< - this line print 5
delete b;
}

这是c ++标准吗?是否有任何魔法标记设置?



VS2008和VS2010? class =h2_lin>解决方案

您的程序根据C ++标准格式不正确,因此表现出不能在C ++标准领域解释的行为。



参考:

C ++ 03标准:



15.4异常规范[except.spec] / strong>



如果一个虚拟函数有一个异常规范,那么覆盖任何函数的所有声明任何派生类中的虚函数只允许基类虚函数的异常规范允许的异常。

[示例:




  struct B 
{
virtual void f()throw );
virtual void g();
};
struct D:B
{
void f(); // ill-formed
void g()throw(int); // OK
};




D :: f 允许所有异常,而 B :: f 只允许 int double 。 ]



Three different compilers show three different behaviours compiling this code:

class MyException : public std::exception
{
 public:
  MyException(std::string str) : m_str(str) {}
  virtual const char * what() const throw () {return m_str.c_str(); }
 protected:
  std::string m_str;
};

Sun C++ 5.8 Patch 121017-22 2010/09/29: Warning Function MyException::~MyException() can throw only the exceptions thrown by the function std::exception::~exception() it overrides

g++ 3.4.3: Error looser throw specifier for `virtual MyException::~MyException()'

Visual Studio 2005: It is very happy (neither error or warning)

class exception {
public:
  exception () throw();
  exception (const exception&) throw();
  exception& operator= (const exception&) throw();
  virtual ~exception() throw();
  virtual const char* what() const throw();
}

I know what the problem is and how I can fix it:

class MyException : public std::exception
{
 public:
  MyException(std::string str) : m_str(str) {}
  virtual const char * what() const throw () {return m_str.c_str(); }
  ~MyException() throw() {}  <------------ now it is fine!
 protected:
  std::string m_str;
};

However I am wondering what the standard says in specific situation.

I ran another small test in Visual Studio 2005 and I have found something that really surprise me:

struct Base
{
    virtual int foo() const throw() { return 5; }
};

struct Derived : public Base
{
    int foo() const { return 6; }
};

int main()
{
    Base* b = new Derived;
    std::cout << b->foo() << std::endl; //<-- this line print 6!!!
    delete b;
}

The signature of the two functions are different. How can this work? It seems that visual studio 2005 completely ignore the exception specification.

struct Base
{
    virtual int foo() const throw() { return 5; }
};

struct Derived : public Base
{
    int foo() { return 6; } // I have removed the const keyword 
                            // and the signature has changed
};

int main()
{
    Base* b = new Derived;
    std::cout << b->foo() << std::endl; // <-- this line print 5
    delete b;
}

Is this c++ standard? Is there any magic flag to set?

What about VS2008 and VS2010?

解决方案

Your program is ill-formed as per the C++ Standard and hence demonstrates a behavior which cannot be explained within the realms of the C++ standard.

Reference:
C++03 Standard:

15.4 Exception specifications [except.spec]

If a virtual function has an exception-specification, all declarations, including the definition, of any function that overrides that virtual function in any derived class shall only allow exceptions that are allowed by the exception-specificationof the base class virtual function.

[Example:

 struct B 
 {
    virtual void f() throw (int, double);
    virtual void g();
 };
 struct D: B 
 {
    void f(); // ill-formed
    void g() throw (int); // OK
 };

The declaration of D::f is ill-formed because it allows all exceptions, whereas B::f allows only int and double. ]

这篇关于什么c ++标准说关于在默认析构函数中丢失throw specifier的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆