C和C++的类型转换
在C语言中如果经常对一些数据类型进行转换的话,可能会在项目中出现一些潜藏的问题bug,之后会非常难以排查错误,在C++中对类型转换有比较安全的好定位的方式
const_cast
这里可以查看代码的执行结果,可以发现,其实这里的修改并没有data的输出,但是奇妙的是修改了指向data地址上的其他指针的内容
#include <iostream>
using namespace std;
int main() {
const int data = 100;
int* pp = (int*)&data;
*pp = 300;
cout << "data = " << data << "\t地址 : " << &data << endl << endl;
cout << " pp = " << *pp << "\t地址 : " << pp << endl << endl;
int* p = const_cast<int*>(&data);
cout << "data = " << data << "\t地址 : " << &data << endl << endl;
cout << " p = " << *p << "\t地址 : " << p << endl << endl;
*p = 200;
cout << "data = " << data << "\t地址 : " << &data << endl << endl;
cout << " p = " << *p << "\t地址 : " << p << endl << endl;
return 0;
}
const 的机制,就是在编译期间,用一个常量代替了 data。这种方式叫做常量折叠。
常量折叠与编译器的工作原理有关,是编译器的一种编译优化。在编译器进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。所以在上面的例子中,编译器在优化的过程中,会把碰到的data(为const常量)全部以内容100替换掉,跟宏的替换有点类似。
但是对于自定义数据类型使用const_cast是不成立的
#include <iostream>
#include <stdio.h>
using namespace std;
class _Test {
public:
int a;
_Test() {
a = 10;
}
} Test;
int main()
{
const _Test b;
_Test* b1 = const_cast<_Test*>(&b);
cout << "b = " << b.a << endl;
b1->a = 100;
cout << "b = " << b.a << ", *b1 = " << b1->a << endl;
return 0;
}
reinterpret_cast
一般都是对引用和指针才使用这个类型转换的函数
#include <iostream>
using namespace std;
int Test()
{
return 0;
}
int main()
{
// C++ reinterpret_cast
//这里定义一个函数指针,并且声明一个变量
typedef void(*FuncPtr) ();
FuncPtr funcPtr;
//funcPtr = &Test;
funcPtr = reinterpret_cast<FuncPtr>(&Test);
int a = 10;
int* p = &a;
char* ptr = reinterpret_cast<char*>(&p);
return 0;
}
static_cast
static_cast的转换相对比较简单
// static_cast
int i = 6;
double d = static_cast<double>(i); //基本类型转换 int -> double
double d2 = 5.6;
int i2 = static_cast<int>(d2); //基本类型转换 double -> int
dynamic_cast
关于dynamic_cast有自动检测的功能
#include <iostream>
using namespace std;
class Father {
public:
Father():my_age(10) {}
virtual void func() {
cout << "This is Faher func" << my_age <<endl;
}
int my_age;
};
class Son:public Father
{
public:
Son() : my_money(999) { ; }
virtual void func() {
cout << "This is Son func :" << my_money << endl;
}
private:
int my_money;
};
int main() {
//首先创建父类和子类的对象
Father fa;
Father* pfa;
Son s;
Son* ps;
//转换,从子类到父类,一般在继承中转换都是从子类到父类比较多,dynamic_cast会有自动检测的功能
//如果转换非常不安全的话,他会将赋值的对象赋值为0
//dynamic_cast只会检测虚函数
//子类转换成父类
pfa = static_cast<Father*>(&s);
if (pfa == NULL) {
cout << "pfa = static_cast<Father*>(&s) is a unsafe way" << endl;
}
pfa = dynamic_cast<Father*>(&s);
if (pfa == NULL) {
cout << "dynamic_cast<Father*>(&s) is a unsafe way" << endl;
}
//父类转换成子类
ps = static_cast<Son*>(&fa);
if (ps == NULL) {
cout << "ps = static_cast<Son*>(&fa) is a unsafe way" << endl;
}
ps = dynamic_cast<Son*>(&fa);
if (ps == NULL) {
cout << "dynamic_cast<Son*>(&fa) is a unsafe way" << endl;
}
return 0;
}
因为子类已经重写了虚函数,如果再向上层转换的话