强制类型转换关闭或挂起了正常的类型检查,要慎用:
(1):static_cast:
static_cast用于(非多态)相关类型的转换(静态转换),即可用于编译器隐式执行的任何类型转换
int i = 12;
double d = static_cast<double>(i);
(2):reinterpret_cast:不相关类型间的强制转换,例子如下:
typedef void(*FUNC)();
int Dosomething(int i)
{
cout << "Dosomething" << endl;
cout<<"i=" << i << endl;
return 0;
}
使用了reinterpret_cast,编译器就以 FUNC 的定义去看待Dosomething函数,所以:
FUNC pf = reinterpret_cast<FUNC>(Dosomething);
(1)pf(); //执行(1)反而是对的,
(2)pf(1);//而(2)传参数了却不对。
所以该强制类型转换要慎用,自己要完全理解所涉及的数据类型
(3):const_cast:用于取消变量的const属性,方便赋值,如下:
const int i = 10;
int * p = const_cast<int *>(&i);
*p = 20;
cout << "i=" << i << endl;//i=10,原因:开始时,i被保存在寄存器里,但修改时,取了i的地址,是对其内存进行了修改,但取i 的值时,取得还是寄存器里的值
若没有使用const_cast, 如下:
const int i = 10;
int * p = &i; //error:需要用const int *p来接受
(4):dynamic_cast:
dynamic_cast只能用于含有虚函数的类
dynamic_cast用于将一个子类对象的指针转换为基类对象的指针或引用(自动转型)
向上转型:子类对象 - >基类指针 / 引用(不需要转型)
向下转型:基类对象 - >子类指针 / 引用(用dynamic_cast转型是安全的)
dynamic_cast会先检查是否能转换成功,能转则转,不能转则返回空,例子如下:
class A
{
public:
virtual void f()
{}
};
class B :public A
{};
void fun(A*pa)
{
B *pb1 = static_cast<B *>(pa);
B *pb2 = dynamic_cast<B *>(pa);
cout << "pb1:" << pb1 << endl;
cout << "pb2:" << pb2 << endl;
}
定义对象并调用fun函数
A a;
B b;
fun(&a); //pb1会输出对象a的地址,pb2会输出空地址
fun(&b); //都会输出对象b的地址
(5):explicit:阻止经过转换构造函数进行的隐式转换的发生
class A
{
public:
explicit A(int a)
{
cout << "A(int a)" << endl;
}
A(const A& a)
{
cout << "A(const A& a)" << endl;
}
private:
int a;
};
(1)A a1(1); //对,调A的构造函数
(2)A a2 = 1;//错,原因:整型1要先发生一个隐式的转换,调A的构造函数产生一个临时的匿名对象,但加了explicit关键字,阻止了该隐式转换
(3)A a3 = A(1);//对,调A的构造函数产生一个匿名对象
(1):static_cast:
static_cast用于(非多态)相关类型的转换(静态转换),即可用于编译器隐式执行的任何类型转换
int i = 12;
double d = static_cast<double>(i);
(2):reinterpret_cast:不相关类型间的强制转换,例子如下:
typedef void(*FUNC)();
int Dosomething(int i)
{
cout << "Dosomething" << endl;
cout<<"i=" << i << endl;
return 0;
}
使用了reinterpret_cast,编译器就以 FUNC 的定义去看待Dosomething函数,所以:
FUNC pf = reinterpret_cast<FUNC>(Dosomething);
(1)pf(); //执行(1)反而是对的,
(2)pf(1);//而(2)传参数了却不对。
所以该强制类型转换要慎用,自己要完全理解所涉及的数据类型
(3):const_cast:用于取消变量的const属性,方便赋值,如下:
const int i = 10;
int * p = const_cast<int *>(&i);
*p = 20;
cout << "i=" << i << endl;//i=10,原因:开始时,i被保存在寄存器里,但修改时,取了i的地址,是对其内存进行了修改,但取i 的值时,取得还是寄存器里的值
若没有使用const_cast, 如下:
const int i = 10;
int * p = &i; //error:需要用const int *p来接受
(4):dynamic_cast:
dynamic_cast只能用于含有虚函数的类
dynamic_cast用于将一个子类对象的指针转换为基类对象的指针或引用(自动转型)
向上转型:子类对象 - >基类指针 / 引用(不需要转型)
向下转型:基类对象 - >子类指针 / 引用(用dynamic_cast转型是安全的)
dynamic_cast会先检查是否能转换成功,能转则转,不能转则返回空,例子如下:
class A
{
public:
virtual void f()
{}
};
class B :public A
{};
void fun(A*pa)
{
B *pb1 = static_cast<B *>(pa);
B *pb2 = dynamic_cast<B *>(pa);
cout << "pb1:" << pb1 << endl;
cout << "pb2:" << pb2 << endl;
}
定义对象并调用fun函数
A a;
B b;
fun(&a); //pb1会输出对象a的地址,pb2会输出空地址
fun(&b); //都会输出对象b的地址
(5):explicit:阻止经过转换构造函数进行的隐式转换的发生
class A
{
public:
explicit A(int a)
{
cout << "A(int a)" << endl;
}
A(const A& a)
{
cout << "A(const A& a)" << endl;
}
private:
int a;
};
(1)A a1(1); //对,调A的构造函数
(2)A a2 = 1;//错,原因:整型1要先发生一个隐式的转换,调A的构造函数产生一个临时的匿名对象,但加了explicit关键字,阻止了该隐式转换
(3)A a3 = A(1);//对,调A的构造函数产生一个匿名对象