异常接口声明也叫异常规范。其实就是,在抛出异常的函数的形参之后,函数体之前,使用throw(),在括号内写明这个函数要抛出的异常。
为什么要有函数规范呢?
因为,我们在开发中可能会使用到别人开发的函数,但是我们最开始是不知道函数具体抛出了写什么异常,我们就需要去读函数的源代码来查看抛出了什么异常,这样会比较不方便。
使用了异常规范之后,我们可以直接根据throw()中内容,知道这个函数抛出了什么类型的异常。
注意: 因为一些原因(比如函数嵌套的情况),异常规范在实际使用时并不是很方便,所以现在一般情况尽可能不要使用,做一个了解就好。有些编译器,即使你写上异常规范,它们也会将它忽略掉。
代码:
void func1() throw(int) {
throw - 1;
printf("func1\n");
}
我们在func1()后面使用了异常规范,指定了这个函数将要抛出的异常。
注意事项:
以下的所有注意事项如果不遵守可能会出错,主要看编译器,有的编译器会忽略异常规范,即使你写了异常规范,不会报错,编译器会自动忽略掉(都忽略了,相当于没用,自然也就不需要注意了),所以即使你有下列的问题,也不会报错。但是,有的编译器会报错。
1. 当我们在函数中使用了异常规范,那么我们函数中抛出的异常类型,就必须是异常规范中指定的类型,不能抛出其它的类型。
2. 如果我们函数中不会抛出异常那么就直接写throw(),()中什么类型也不需要写。这样,我们的函数中就不能抛出任何类型的异常。
3. 如果使用了异常规范,那么在函数的声明和函数的定义中都得写,而且两个的异常规范必须一致。
// 正确,声明和定义都写了异常规范,且一样
void func1() throw(int);
void func1() throw(int) {
throw 1;
printf("func1\n");
}
// 错误, 声明和定义虽然都写了异常规范,但是不一样
void func1() throw();
void func1() throw(int) {
throw 1;
printf("func1\n");
}
// 错误,声明中没有写异常规范
void func1();
void func1() throw(int) {
throw 1;
printf("func1\n");
}
// 错误,定义中没有写异常规范
void func1() throw(int);
void func1(){
throw 1;
printf("func1\n");
}
4. 如果没有包含任何的异常规范,那么此函数可以抛出任何类型的异常。
在父类和派生类之间,如果父类中的函数使用了异常规范,那么子类在重写了这个函数之后,其的异常规范要么和父类的严格一样,要么比父类的更加严格。
什么叫更严格呢?
throw() 比 throw(int) 更加严格,因为前者不允许抛出异常,而后者允许抛出int类型的异常。
throw(int) 比 throw(int,float) 更加严格,因为前面只允许抛出int类型的异常,而后者允许抛出int类型和float类型的异常。
代码:
class A {
public:
void func1()throw(int,float) {
throw - 1;
}
};
class B :public A {
public:
void func1()throw(int) {
throw - 1;
}
};
类B继承了类A,那么类B重写的func1函数的异常规范应该与类A中的相同或者更加严格。 代码中就是更加严格。
注意: 上面所说的,如果编译器忽略异常规范,那么你即使写了它也会忽略,就相当于没写,所以也不会有上述的问题和注意事项了。
但是即使编译器忽略了,但是我们写上也可以提高可读性。将抛出的异常写上。只是编译器不会检测了,但是可以给读者看