速通C++类型转换(代码+注释)
本文包含以下内容:
1、对C语言两种主要的类型转换方式的回顾
2、C++中内置类型->自定义类型、自定义类型->内置类型、自定义类型->自定义类型的转换方式
3、C++和C语言都不是类型安全的语言
4、C++四种显示强制类型转换:static_cast, reinterpret_cast, const_cast, dynamic_cast
5、RTTI基本理解(RUNTIME TYPE IDENTIFICATION)
class A
{
public://explicit A(int a);//有explicit就不再支持隐式类型转换//如果还想使用类型转换,直接强制类型转换即可A(int a): _a1(a), _a2(a){//有构造函数可以支持内置-》自定义}A(int a, int b): _a1(a), _a2(b){}int get1(){return _a1;}int get2(){return _a2;}//自定义类型转换成内置类型——也是支持的隐式的类型转换operator int() const{return _a1 + _a2;}
private:int _a1;int _a2;
};class B
{
public:B(int b1, int b2): _b1(b1), _b2(b2){}B(const A& aa)//自定义类型转换成自定义类型: _b1((int)aa), _b2((int)aa){}
private:int _b1;int _b2;
};int main()
{//不是所有类型都支持类型转换,有意义的才支持隐式类型转换//char ch = 'a';//int i = &ch;//这里就不可以int i = (int)(&ch);//只能采取这种显示强制的方式//double j = (double)&i;//这样的强制类型转换也不可以//C++还支持内置类型和自定义类型的转换//内置类型转换成自定义类型需要operator类型()//自定义类型转换成内置类型需要构造函数A a = 1;A aa = (1, 1);//这是逗号表达式,多参数需要使用花括号A aaa = { 1, 1 };//自定义类型转换为内置类型int b = a;cout << b << endl;//自定义类型转换成内置类型的应用场景——转换成了boolshared_ptr<int> sp1;shared_ptr<int> sp2(new int);if (sp1){cout << "1" << endl;}if (sp2){cout << "2" << endl;}//自定义类型和自定义类型也可以进行转换,通过构造函数A a1(1);B d = a1;//应用场景——之前写的链表,这里不涉及权限的转化问题//wjl::list<int>::const_iterator cit = lt.begin();//C和C++都不是类型安全的语言,因为他们都允许类型转换const int i1 = 0;int* p = (int*)&i1;volatile const int i2 = 0;int* p2 = (int*)&i2;(*p) = 1; (*p2) = 1;cout << i1 << endl;//0cout << *p << endl;//1cout << *p2 << endl;//这里打印的结果是因为类型转换使i1失去了const属性,编译器认为y是const的//不会被改变,所以将其放进了寄存器或者直接替换y为0导致的//但是一旦加上了valatile,就可以让编译器直接上内存中找相应数据//C++中四个显示强制类型转换运算符//static_cast对应隐式类型转换,数据的解释意义没有发生改变(只要底层不适用const)double f = 12.34;int e = static_cast<int> (f);cout << e << endl;int&& g = static_cast<int&&>(f);//reinterpret_cast,用于两个意义不太相近的转换,转换后对内存的访问解释//已经完全改变了int* h = reinterpret_cast<int*>(e);//cout << *h << endl;//const_cast只能作用于指针或者引用,可以将const对象转换成非const对象const int l = 1;int* m = const_cast<int*>(&l);//dynamic_cast用于将基类的指针或引用转换成派生类的指针或者引用//如果基类的指针或引用指向的是派生类,那么转换成功;如果基类的指针或者引用//指向基类,则转换失败,抛出bad_cast异常;同时,dynamic_cast还要求基类//满足多态,即内部有虚函数,因为dynamic_cast是通过虚表中指向的type_info//来判断是基类还是派生类的(这种转换是安全的)//RTTI运行时类型识别Runtime Type Identification//指的是程序在运行的的时候才能确定需要用到的对象是什么类型,用于在运行时获取//有关类型的信息,RTTI主要通过typeid和dynamic_cast实现typedef class A alpha;cout << typeid(alpha).name() << endl;cout << typeid(10).name() << endl;cout << typeid(string).name() << endl;//typeid不完全是RTTI,dynamic_cast是完全的RTTI,B* pbb = new B{ 1, 1 };A* paa = (A*)pbb;if (typeid(*pbb) == typeid(B)){cout << "typeid(*pbb) == typeid(B)" << endl;}//这里就是RTTI的体现,类似于dynamic_cast,通过虚表指针发现基类的指针或者引用指向的是派生类/*if (typeid(*paa) == typeid(B)){cout << "typeid(*paa) == typeid(B)" << endl;}假设这里A是多态,B对A进行了继承*/if (typeid(paa) == typeid(pbb)){cout << "typeid(paa) == typeid(pbb)" << endl;}//不是类类型对象,就会被当作静态对象处理,在编译时就确定return 0;
}