类型转换
静态类型转换 static cast
可以用于基础数据类型和父子数据类型之间的转换,如果是不是上面两种形式,就不允许转换
动态类型转换 dynamic cast
只有发生多态的情况,才可以使用,其他情况都不能使用
class Father{};
class Son:public Father{};
int main(int argc, const char * argv[]) {
Father* f = new Father;
Son* s = new Son;
s = static_cast<Son*>(f);
f = dynamic_cast<Son*>(s);
}
常量转换 const_cast
用于指针或引用的 const/非const 类型之间的转换
reinterpret_cast 转换
类似于c语言的强转。。。不安全,不推荐
异常
捕获int类型异常(异常必须捕获,否则系统会调用 terminating 函数让程序中断)
int myDevide(int a,int b){
if(b == 0){
throw -1;
}
return a / b;
}
int main(int argc, const char * argv[]){
try {
int ans = myDevide(2, 0);
cout << ans << endl;
} catch (int) {
cout << "not zero" << endl;
}catch (double){
throw; //也可以继续向上抛出异常,这里由于已经是main函数,没有接收异常的函数,程序中断
}catch(...){ //...捕获所有类型的异常
}
}
可以使用 … 捕获所有类型的异常
自定义异常
class MyException{
public:
void printErr(){
cout << "抛出了异常" << endl;
}
};
int myDevide(int a,int b){
if(b == 0)
{
throw MyException();
}
return a / b;
}
int main(int argc, const char * argv[]){
try {
myDevide(1,0);
} catch (MyException e) {
e.printErr();
}
}
栈解旋 从try开始到throw抛出异常前,栈上所有的对象都会被释放a
异常的接口声明
在类unix系统中可以这么写,windows下无效
void func() throw(int){
throw 1;
}
void func() throw(){ //所有类型
}
void func() throw(int,char){ //抛出int和char类型
}
这里显式指定抛出的异常类型为int,如果抛出的类型不为int则不会被抛出
异常类型的生命周期
class MyException{
public:
MyException(){
cout << "构造函数" << endl;
}
MyException(const MyException& exception){
cout << "拷贝构造函数" << endl;
}
~MyException(){
cout << "析构函数" << endl;
}
};
int myDevide(int a,int b){
if(b == 0)
{
throw MyException();
}
return a / b;
}
int main(int argc, const char * argv[]){
try {
myDevide(1, 0);
} catch (MyException e) {// MyException& e
cout << "异常" << endl;
}
}
输出:
构造函数
拷贝构造函数
异常
析构函数
析构函数
可以发现,析构函数的调用在catch之后,因此我们可以把 catch 中的 MyException 改成引用类型,避免拷贝构造带来的开销。
异常同样可以配合多态一起使用,实现一个公共接口,这样可以使用父类来接收所有子类型异常。java中的Exception就是这样的呢~。
系统异常类
自定义标准库异常
就是实现一个虚函数和虚析构
class MyException:public exception{
private:
string err;
public:
MyException(string err){
this->err = err;
}
const char* what(){
return err.c_str();
}
~MyException(){
}
};