Jam*_*lis 13 c++ destructor exception-handling exception exception-specification
C++标准声明了以下关于具有异常规范的虚函数:
如果虚函数具有异常规范,则任何在任何派生类中覆盖该虚函数的函数的所有声明(包括定义)都只允许基类虚函数的异常规范所允许的异常(C +) +03§15.4/ 3).
因此,以下是不正确的:
struct B {
virtual void f() throw() { } // allows no exceptions
};
struct D : B {
virtual void f() { } // allows all exceptions
};
Run Code Online (Sandbox Code Playgroud)
(1)此规则是否适用于析构函数?也就是说,以下是否良好?
struct B {
virtual ~B() throw() { }
};
struct D : B {
virtual ~D() { }
};
Run Code Online (Sandbox Code Playgroud)
(2)此规则如何应用于隐式声明的析构函数?也就是说,以下是否良好?
struct B {
virtual ~B() throw() { }
};
struct D : B {
// ~D() implicitly declared
};
Run Code Online (Sandbox Code Playgroud)
虽然在一般情况下,永远不应该编写异常规范,但这个问题具有实际意义,因为std::exception析构函数是虚拟的并且具有空的异常规范.
因为最好不要从析构函数中抛出异常,所以我们假设为了简化析构函数允许所有异常(也就是说,它没有异常规范)或者它不允许异常(是,它有一个空的异常规范).
Jam*_*lis 13
是的,这个规则适用于析构函数(析构函数的规则没有例外),所以这个例子是不正确的.为了使其格式良好,异常规范~D()必须与~B()例如,
struct B {
virtual ~B() throw() { }
};
struct D : B {
virtual ~D() throw() { }
};
Run Code Online (Sandbox Code Playgroud)
C++标准说明了以下关于隐式声明的特殊成员函数:
隐式声明的特殊成员函数应具有异常规范.
如果
f是隐式声明的默认构造函数,复制构造函数,析构函数或复制赋值运算符,则其隐式异常规范指定type-id,T当且仅当T由f隐式定义直接调用的函数的异常规范允许时;
f如果它直接调用的任何函数允许所有异常,则允许所有异常,并且f如果它直接调用的每个函数都不允许异常,则不允许异常(C++03§15.4/ 13).
隐式声明的析构函数直接调用哪些函数?
在执行析构函数体并破坏正文中分配的任何自动对象之后,为类
X调用执行析构函数
X直接成员的破坏者,- 用于
X直接基类的析构函数,以及- if
X是派生类最多的类,它的析构函数调用析构函数X的虚拟基类(C++03§12.4/ 6;重新格式化以便于阅读).
因此,隐式声明的析构函数具有异常规范,允许任何这些析构函数允许的任何异常.要考虑问题中的示例:
struct B {
virtual ~B() throw() { }
};
struct D : B {
// ~D() implicitly declared
};
Run Code Online (Sandbox Code Playgroud)
隐式声明的唯一析构函数~D()是~B().由于~B()不允许任何异常,因此~D()不允许异常,就像声明它一样virtual ~D() throw().
这个异常规范显然与~B()'s 兼容,所以这个例子是格式良好的.
作为解决这个问题的实际例子,请考虑以下事项:
struct my_exception : std::exception {
std::string message_;
};
Run Code Online (Sandbox Code Playgroud)
~string()允许所有异常,因此隐式声明~my_exception()允许所有异常.基类析构函数~exception()是虚拟的,不允许任何异常,因此派生类析构函数与基类析构函数不兼容,这是不正确的.
为了使这个示例格式正确,我们可以使用空异常规范显式声明析构函数:
struct my_exception : std::exception {
virtual ~my_exception() throw() { }
std::string message_;
};
Run Code Online (Sandbox Code Playgroud)
虽然经验法则永远不会编写异常规范,但至少有一个常见的情况是这样做是必要的.
| 归档时间: |
|
| 查看次数: |
5139 次 |
| 最近记录: |