C++ STL——类型转换
目录
注:原创不易,转载请务必注明原作者和出处,感谢支持!
注:内容来自某培训课程,不一定完全正确!
一 类型转换
类型转换的含义是通过改变一个变量的类型为别的类型从而改变变量的表示方式。C++提供了4种类型转换操作符来应对不同场合的类型转换。
语法 | 适用场景 |
---|---|
static_cast |
一般的转换(比如C++内建类型之间的转换) |
dynamic_cast |
通常在基类和派生类之间转换时使用 |
const_cast |
主要针对const的转换 |
reinterpret_cast |
用于进行没有任何关联之间的转换,比如一个字符指针转换为一个整型数 |
总结:
(1)static_cast
用于内置数据类型,具有继承关系的指针或者引用的转换。
(2)dynamic_cast
只能转换具有继承关系的指针或者引用,并且只能由子类型转成父类型(基类型)。在具有基础关系的指针或者引用的转换上,相较于static_cast,dynamic_cast,添加了额外的安全检查,拒绝了类型不安全的转换,更加地安全。
(3)const_cast
用来给基础数据类型,指针或者引用“加上”或者“去除”const
(4)reinterpret_cast
用于任意两个无关类型的指针或者引用的转换
有关C++类型转换的一个详细案例如下所示。
class Building {};
class Animal {};
class Cat : public Animal {};
void Test1()
{
// static_cast
int a = 65;
char c = static_cast<char>(a);
cout << c << endl;
// 基础数据类型的指针 - 无法转换
// int *p = nullptr;
// char *sp = static_cast<char *>(p);
// 对象指针 - 无法转换
// Building *building = nullptr;
// Animal *ani = static_cast<Animal *>(building);
// 转换具有基础关系的对象指针
// 父类指针转子类指针
Animal *ani = nullptr;
Cat *cat = static_cast<Cat *>(ani);
// 子类指针转父类指针
Cat *soncat = nullptr;
Animal *anifather = static_cast<Animal *>(soncat);
// 父类引用转子类引用
Animal aniobj;
Animal &aniref = aniobj;
Cat &catref = static_cast<Cat &>(aniref);
// 子类引用转父类引用
Cat catobj;
Cat &catref2 = catobj;
Animal & aniref2 = static_cast<Animal &>(catref2);
// 总结:static_cast用于内置数据类型,具有继承关系的指针或者引用的转换
}
void Test2()
{
// dynamic_cast只能转换具有继承关系的指针或者引用
// 其在转换之前会进行对象类型的检查
// 内建数据类型的转换 - 无法转换
// dynamic_cast中的类型必须是指向完整类类型或者void *的指针或者引用
// int a = 10;
// char c = dynamic_cast<char>(a);
// 非继承关系的指针的转换 - 无法转换,两者不具备继承关系
// Animal *pani = nullptr;
// Building *pbuilding = dynamic_cast<Building *>(pani);
// 具有继承关系的指针 - 无法转换,父类指针转子类指针是类型不安全的
// Animal *pani = nullptr;
// Cat *pcat = dynamic_cast<Cat *>(pani);
// 具有继承关系的指针 - 可以转换,子类指针转换为父类指针是类型安全的
Cat *pcat = nullptr;
Animal *pani = dynamic_cast<Animal *>(pcat);
// 具有基础关系的引用 - 无法转换,原因同样是父类引用转换成子类引用是类型不安全的
// Animal aniobj;
// Animal &aniref = aniobj;
// Cat &catref = dynamic_cast<Cat &>(aniref);
// 具有继承关系的引用 - 可以转换,子类引用转父类引用是类型安全的
Cat catobj;
Cat &catref = catobj;
Animal &aniref = dynamic_cast<Animal &>(catref);
// 总结:dynamic_cast只能转换具有继承关系的指针或者引用
// 并且只能由子类型转成父类型(基类型)
// 在具有基础关系的指针或者引用的转换上,相较于static_cast,dynamic_cast
// 添加了额外的安全检查,拒绝了类型不安全的转换,更加地安全
}
void Test3()
{
// 基础数据类型
int a = 10;
const int &b = a;
// b = 20; b为const引用,无法通过b来修改a的值
// 通过const_cast去除const
int &c = const_cast<int &>(b);
// 通过引用c来修改a的值
c = 20;
// a值为20现在
cout << "a = " << a << endl;
// 指针
// 去除const
const int *p1 = nullptr;
int *p2 = const_cast<int *>(p1);
// 加上const
int *p3 = nullptr;
const int *p4 = const_cast<const int *>(p3);
// 引用 - 去除const
int k = 20;
const int &r1 = k;
int &r2 = const_cast<int &>(r1);
// 引用 - 加上const
int j = 30;
int &r3 = j;
const int &r4 = const_cast<const int &>(r3);
// 总结:const_cast用来给基础数据类型,指针或者引用“加上”或者“去除”const
}
typedef void(*func1)(int, int);
typedef int(*func2)(int, char*);
void Test4()
{
// 基础数据类型 - 无法转换
// int a = 10;
// char c = reinterpret_cast<char>(a);
// 指针
Building *pbuilding = nullptr;
Animal *ani = reinterpret_cast<Animal *>(pbuilding);
// 引用
Building building;
Building &bref = building;
Animal &aniref = reinterpret_cast<Animal &>(bref);
// 函数指针
func1 f1;
func2 f2 = reinterpret_cast<func2>(f1);
// 总结:reinterpret_cast用于任意两个无关类型的指针或者引用的转换!
// 应该尽量避免在代码中使用类型转换!!!
}