类型转换的含义是通过改变一个变量的类型为别的类型从而改变该变量的表示方式。为 了类型转换一个简单对象为另一个对象你会使用传统的类型转换操作符。
c 风格的强制类型转换,不管什么是什么类型,统统都是 Type b = (Type)a; c++风格的类型转换提供了 4 种类型转换操作符来应对不同场合的的应用。
定义这几个类
#include<iostream>
#include"MyVector.hpp"
using namespace std;
class Animal
{
public:
int mA;
int mB;
};
class Cat : public Animal
{
public:
int mC;
};
class Building
{
public:
int mA;
};
1,static_cast 它能在内置的数据类型间互相转换,对于类只能在有联系的指针类型间进行转换。可以在继承体系中把指针转换来、转换去,但是不能转换成继承体系外的一种类型。
- (1) 基础类型转换,可隐式类型转换都可用 static_cast - 可行
- (2) 指针类型 不相关类型转换 - 失败
- (3) 基类指针和子类指针转换 - 可行
//父类指针转成子类指针(不安全)
不安全是指,cat比父类animal多了个属性mC,如果进行强转,可能ani无法访问新的属性mC
//子类指针转成父类指针(安全)
子类指针包含父类指针的所有属性,所以访问不会出现访问非法的问题。 - (4) 引用类型转换
- //父类指针转换为子类指针- 不安全
- //子类指针转换为父类指针- 可行
void test01(){
double dpi = 3.1415;
//1 基础类型转换,可隐式类型转换都可用 static_cast - 可行
int ipi = static_cast<int>(dpi);
//2 指针类型 不相关类型转换 - 失败
char* p = "abcdefg";
int* addr = static_cast<int*>(p);//error
//3 基类指针和子类指针转换 - 可行
//父类指针转成子类指针(不安全)
//不安全是指,cat比父类animal多了个属性m_c,如果进行强转,可能ani无法访问新的属性
Animal* ani1 = new Animal;
Cat* cat1 = static_cast<Cat*>(ani1);
//子类指针转成父类指针(安全)
Cat* cat2 = new Cat;
Animal* ani2 = static_cast<Animal*>(cat2);
//4. 引用类型转换
//父类指针转换为子类指针- 不安全
Animal ani4;
Animal& ani_ref = ani4;
Cat& cat_ref = static_cast<Cat&>(ani_ref);//不会报错
//子类指针转换为父类指针- 可行
Cat cat;
Cat& cat_ref = cat;
Animal& ani = static_cast<Animal&>(cat_ref);
}
2.dynamic_cast 仅能应用于指针或者引用,不支持内置数据类型 。它不仅仅像 static_cast 那样,检查转换前后的两个指针是否属于同一个继承树,它还要检查被指针引用的对象的实际类型,确定转换是否可行。
- (1) 转换内置数据类型 - 失败
- (2) 转换父子关系类
//父类指针转换为子类指针- 失败
//子类指针转换为父类指针- 可行
原理和static_cast一样。 - (3)不同类型指针转换 -失败
- (4) 引用转换-可行
void test02()
{
//1 转换内置数据类型 - 失败
double dpi = 3.1415;
int ipi = dynamic_cast<int>(dpi); //error
//2. 转换父子关系类
Animal* ani1 = new Cat;
//父类指针转换为子类指针- 失败
Cat* cat1 = dynamic_cast<Cat*>(ani);//error
//子类指针转换为父类指针- 可行
Cat* cat2 = new Cat;
Animal* ani2 = dynamic_cast<Animal*>(cat);
//3. 不同类型指针转换 - 失败
Cat* cat3 = new Cat;
Building* building = dynamic_cast<Building*>(cat3); //error
//4. 引用转换
//父类指针转换为子类指针- 失败
Animal ani4;
Animal& ani_ref = ani4;
Cat& cat_ref = dynamic_cast<Cat&>(ani_ref);//error
//子类指针转换为父类指针- 可行
Cat cat;
Cat& cat_ref = cat;
Animal& ani = dynamic_cast<Animal&>(cat_ref);
}
3.cosnt_cast 去掉类型中的常量性 也就是去掉const关键字,
const_cast 中的类型必须是指针、引用或指向对象类型成员的指针
void test03()
{
//对象指针
const Building* const_buding = new Building;
const_buding->mA = 10; //const 修饰,不可修改 error
Building* nonconst_buding = const_cast<Building*>(const_buding);
nonconst_buding->mA = 10;//可以修改
//引用
int a = 10;
const int& b = a;
//b = 10; //不可修改
int& c = const_cast<int&>(b);
c = 20;
cout << "a:" << a << endl;
//给指针加上 const 性
Building* nonconst_budingVal = new Building;
nonconst_budingVal->mA = 10; //可行
const Building* const_budingVal = const_cast<const Building*>(nonconst_budingVal);
const_budingVal->mA = 20; //不可行 error
nonconst_budingVal->mA = 20; //还是可行的
}
4.reinterpret_cast 任何指针都可以转换成其它类型的指针,感觉该转换很强大,但是IBM的C++指南、C++之父Bjarne Stroustrup的FAQ网页和MSDN的Visual C++也都指出:错误的使用reinterpret_cast很容易导致程序的不安全,只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。
typedef void(*FUNCPTR1)(int, int);
typedef int(*FUNCPTR2)(char);
void test04()
{
//1. 转换基础数据类型
int a = 10;
char c = reinterpret_cast<char>(a); //不可行
//2. 指针类型转换
Animal* ani = new Animal;
Building* building = reinterpret_cast<Building*>(ani);
//3. 函数指针转换
FUNCPTR1 func1 = NULL;
FUNCPTR2 func2 = reinterpret_cast<FUNCPTR2>(func1);
//4. 转换引用
int a = 10;
int& b = a;
char& c = reinterpret_cast<char&>(b);
c = 'a';
}
总结
结论 1:程序员必须清楚的知道要转变的变量,转换前是什么类型,转换后是什么类型, 以及转换后有什么后果。
结论 2:一般情况下,不建议类型转换,避免进行类型转换。
结论3:一般情况下,父类指针转换成子类指针会有问题,子类指针转换成父类指针没有问题。
感谢点赞!!!