我看到了下面的代码片段:
class Foo
{
public:
void virtual func() throw (int, float) = 0;
};
class Bar : public Foo
{
public:
void virtual func() throw(short); // line 1: compile error "
// looser throw specifier"
void virtual func() throw(); // line 2: can compile
void virtual func() throw(float, int); // line 3: can compile
void virtual func() throw(float); // line 4: can compile
void virtual func() throw(int); // line 5: can compile
};
int main(void)
{
return 1;
}
Q1>
是什么意思void virtual func() throw (int, float) = 0;
Q2>为什么line1不能通过编译?
谢谢
最佳答案
让我们分解一下。声明:
void virtual func() throw (int, float) = 0;
有 2 个构造,您正在询问。 =0
构造告诉编译器声明的函数是“抽象的”,这告诉编译器不需要在 class Foo
中定义该函数(尽管它可以是- 但它通常不是)并且不能直接创建 class Foo
的对象 - 无论是作为本地对象、全局对象还是通过 new
。但是,您可以拥有指向 class Foo
对象的指针或引用。某些派生类需要将该函数重写为非抽象函数 - 可以直接创建该类的对象(只要没有其他抽象函数尚未“具体化”)。
throw (int, float)
结构是一个异常规范。这告诉编译器该函数的约定是,如果它抛出异常,它只会抛出 int
或 float
类型的异常。如果该函数抛出某种其他类型的异常,则编译器有义务进行特殊处理(通过调用 std::unexpected()
)。
现在,如果您尝试使用以下声明在派生类中覆盖该函数:
void virtual func() throw(short);
您是说该函数的约定是,如果抛出异常,它将抛出 short
类型的异常。但是,抛出 short
不是被覆盖函数的约定的一部分,因此编译器不允许这样做。
如果您像这样声明覆盖:
void virtual func() throw(float);
你是说重写可以抛出一个 float
,这是原始声明契约的一部分(如果它从不抛出一个 int
违背契约——原始契约只说允许该函数抛出一个int
,而不是它必须抛出的)。
标准的相关部分是 15.4/3 异常规范:
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-specification of the base class virtual function.
请注意,该标准明确指出异常规范不是函数类型的一部分 (15.4/12),因此函数指针可以指向具有不同异常规范的函数。
关于C++ 异常在虚函数上抛出注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3763457/