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性质,编译器就不再阻止我们对该对象的写操作,结果是未定义的。
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只是告诉编译器不能修改而不是真正地不可修改,如果程序员不注意而去修改了它会报错,现在我们利用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
参考:
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
因篇幅问题不能全部显示,请点此查看更多更全内容