C++ Primer笔记2_四种类型转换_异常机制
1.类型转换
命名的强制类型转换:
有static_cast、dynamic_cast、const_cast、reinterpret_cast
static_cast:
编译器隐式运行的不论什么类型转换都能够由static_cast完毕
当一个较大的算术类型赋值给较小的类型时。能够用static_cast进行强制转换。
能够将void*指针转换为某一类型的指针
能够将基类指针强制转换为派生类指针,可是不安全。
无法将const转化为nonconst。这个仅仅有const_cast才干够办得到
举例:
double d = static_cast<double>(j) / i; void *p = &d; double *dp = static_cast<double*>(p);
const_cast:
用来移除对象的常量性(cast away the constness), const_cast一般用于指针或者引用。
对于将常量对象转换为很常量对象的行为,一旦去掉了const性质。编译器就不再阻止我们对该对象的写操作,结果是没有定义的。
const char *pc; char *p = const_cast<char*>(pc);//正确:可是通过p写值是没有定义的行为;
char *p = static_cast<char *>(pc);//错误。static_cast不能转换掉const性质 static_cast<string>(pc);//正确。字符串字面值转换为string const_cast<string>(pc);//错误,const_cast仅仅改变常量属性
看以下一个样例:
#include <iostream> using namespace std; int main(void) { const int a = 100; int *pA = const_cast<int *>(&a); *pA = 200; int &refA = const_cast<int &>(a); refA = 300; // int *pA1 = static_cast<int *>(&a); Error cout << "*pA:" << *pA << endl;//300 cout << "refA:" << refA << endl;//300 cout << "a:" << a << endl;//100 return 0; }
发现通过const_cast转换后,去除了const属性,然后对变量改动,执行时内存中的值是改变的,但最后打印改动后的值仍为原样。
以下是网上摘录的一段解释:
const仅仅是告诉编译器不能改动而不是真正地不可改动,假设程序猿不注意而去改动了它会报错。如今我们利用const_cast去除了常量性,然后通过指针和引用对其进行了改动,所以通过指针打印或者引用传參的时候就能看出其内存确实变化了,但为了保护val这个变量本来的const特性,所以每次我们使用val时。系统都将其替换成初始值100,确保了val还是“不可变”的
常为运算对象的位模式提供较低层次上的又一次解释。
举例:
int *pi; char *pc = reinterpret_cast<char *>(pi);我们必须牢记pc所指的真实对象是一个int而非字符,假设把pc当成字符指针在执行时可能出错。
如:string str(pc);
使用reinterpret_cast时很危急的,一般避免使用。
dynamic_cast:
dynamic_cast主要用于类层次间的上行转换和下行转换,还能够用于类之间的交叉转换。
在类层次间进行上行转换时。dynamic_cast和static_cast的效果是一样的。
在进行下行转换时。dynamic_cast具有类型检查的功能,比static_cast更安全。
1. 安全的基类和子类之间转换。
2. 必需要有虚函数。
3. 同样基类不同子类之间的交叉转换。但结果是NULL。
样例:
#include <iostream> using namespace std; class A { protected: int n; public: A(){n = 10;} virtual void getN(){} }; class B : public A { string name; public: B(){name = "SCOTT";} virtual void getN() { cout << "B: " << n << endl; } void printf() { cout << "name: " << name << endl; } }; void Test(A * pA) { B *pB1 = static_cast<B *>(pA); cout << "pB1: " << pB1 << endl; B *pB2 = dynamic_cast<B *>(pA); cout << "pB2: " << pB2 << endl; } int main() { A *pA1 = new A; A *pA2 = new B; Test(pA1);//pB2为空指针 dynamic_cast将做类型检查,pB1尽管正确,但对其操作是不安全的,从这里能够看出static_cast没有dynamic安全 Test(pA2);//OK 都是B类型对象 return 0; }
总结:
去掉const属性用const_cast
主要的类型转换用static_cast
多态类之间的类型转换用dynamic_cast
不同类型指针类型转换用reinterpret_cast
參考:
http://blog.csdn.net/ljz888666555/article/details/4541232
http://blog.csdn.net/jnu_simba/article/details/8868530
2.异常机制
try-catch-throw的使用:
#include <iostream> using namespace std; double fun(int a, int b) { if(0 == b) { throw b; } return a/b; } int main() { double a = 0.0; try { a = fun(2, 0); } catch(int) { cout << "Error: b is zero!" << endl; } catch(...) { cout << "Other error!" << endl; } cout << "a: " << a << endl;//still run after deal exception return 0; }
自己定义异常类:
#include <iostream> using namespace std; class MyException { public: MyException(string name = "default name") { cout << "New Exception: " << name << endl; this->name = name; } ~MyException() { cout << "Delete Exception: " << this->name << endl; } void myThrow() { throw MyException("Error"); } private: string name; }; int main() { MyException m("Test"); try { m.myThrow(); } catch(...) { cout << "*****" << endl; } return 0; }执行结果:
New Exception: Test New Exception: Error ***** Delete Exception: Error Delete Exception: Test