文章目录
类型转换(cast):将一种数据类型转换为另一种数据类型。
标准C++提供显式转换的语法,基于模板技术实现,以替代C风格的类型转换,可更好地控制强制转换的过程,允许控制各种不同类型的强制转换,且能够清晰地表明作用。
注:C++实际开发中,应尽可能少地使用类型转换,除非用于解决非常特殊的问题,如
string
和const char *
之间的类型转换。应考虑重新设计数据结构,避免过多的类型转换。
1 静态类型转换(static_cast)
语法:目标数据类型 变量/对象 = static_cast<目标数据类型>(原变量/对象);
作用:
(1)用于内置基本数据类型之间的转换。如int和char类型之间的互相转换,安全性需开发人员保证。
(2)用于类层次结构中父类和子类之间指针或引用的转换。
上行转换:子类的指针或引用转换为父类表示,安全。
下行转换:父类的指针或引用转换为子类表示,由于没有动态类型检查,可能导致指针寻址越界,不安全。
注1:子类对象占用的内存空间大于父类对象,因此子类的指针或引用可访问的内存范围更大。
向上转换(子类转化为父类表示)时是安全的;
向下转换(父类转化为子类表示)时是不安全的。
注2:非关联类之间不可进行静态类型转换,否则编译器报错:类型转换无效
。
示例:静态类型转换
#include <iostream>
using namespace std;
//静态类型转换-内置基本数据类型的转换
void func1() {
char ch = 'a';
double d = static_cast<double>(ch);
cout << d << endl; //97
}
class Father {
};
class Son : public Father {
}; //继承
class Other {
}; //非关联类
//静态类型转换-继承中父子类指针的转换
void func2() {
Father* father = NULL;
//向下转换-不安全
Son* son = static_cast<Son*>(father);
//向上转换-安全
Father* f = static_cast<Father*>(son);
//无效转换:非关系类之间不可进行静态类型转换
//Other* other = static_cast<Other*>(father); //报错:类型转换无效
}
//静态类型转换-继承中父子类引用的转换
void func3() {
Father f;
Son s;
Father& father = f;
Son& son = s;
//向下转换-不安全
Son& s1 = static_cast<Son&>(father);
//向上转换-安全
Father& f1 = static_cast<Father&>(son);
//无效转换:非关系类之间不可进行静态类型转换
//Other& other = static_cast<Other&>(father); //报错:类型转换无效
}
2 动态类型转换(dynamic_cast)
语法:目标数据类型 对象 = dynamic_cast<目标数据类型>(原对象);
作用:
(1)不支持内置基本数据类型之间的转换,否则编译器报错:dynamic_cast中的类型必须是指向完整类类型或 void* 的指针或引用
。
注1:动态类型转换
dynamic_cast
会规避不安全的情况,存在安全风险时,不允许类型转换。
注2:动态类型转换dynamic_cast
不支持内置基本数据类型之间的转换。
内置基本数据类型转换时,可能存在精度丢失
(如double类型转换为float类型)、数据截断
(如4字节的int类型转换为1字节的char类型)等安全隐患。
(2)主要用于类层次结构中父类和子类之间指针或引用的转换,如多态调用和上行转换,不支持下行转换的不安全情况。
①多态调用:父类指针或引用指向子类对象,发生多态时,编译器认为类型转换总是安全的,支持多态调用时的下行转换。【支持转换】
②上行转换:子类的指针或引用转换为父类表示,安全,与static_cast
效果相同。【支持转换】
③下行转换:父类的指针或引用转换为子类表示,不安全,dynamic_cast
具有动态类型检查功能,不支持下行转换,否则编译器报错:运行时dynamic_cast的操作数必须包含多态类类型
。【不支持转换】
示例:动态类型转换
#include <iostream>
using namespace std;
//动态类型转换-不支持内置基本数据类型的转换
void func1() {
char ch = 'a';
//报错:dynamic_cast 中的类型必须是指向完整类类型或 void* 的指针或引用
//double d = dynamic_cast<double>(ch); //转换失败
}
class Father {
};
class Son : public Father {
};
class Other {
}; //非关联类
//动态类型转换-支持上行转换,不支持下行转换
void func2() {
/* 不允许向下转换-不安全 */
//报错:运行时dynamic_cast的操作数必须包含多态类类型
Father* father = NULL;
//Son* son = dynamic_cast<Son*>(father); //转换失败
/* 允许向上转换-安全 */
Son* son = NULL;
Father* f = dynamic_cast<Father*>(son); //转换成功
//无效转换:非关系类之间不可进行动态类型转换
//报错:运行时dynamic_cast的操作数必须包含多态类类型
//Other* other = dynamic_cast<Other*>(father);//转换失败
}
class Animal {
virtual void test() {
}
};
class Dog : public Animal {
//重写父类虚函数
virtual void test() {
}
};
//动态类型转换-支持多态调用
void func3() {
//发生多态时,编译器认为类型转换总是安全的
Animal* animal = new Dog;
//支持多态调用时的下行转换
Dog* dog = dynamic_cast<Dog*>(animal);
}
3 常量类型转换(const_cast)
语法:
添加const修饰:const 指针/引用类型 变量 = const_cast<const 指针/引用类型>(原变量);
去除const修饰:指针/引用类型 变量 = const_cast<指针/引用类型>(const修饰的变量);
作用:仅适用于修改指针或引用类型的const
属性,如常量指针/引用与非常量指针/引用的转换。
(1)常量指针被转化为非常量指针,且仍指向原对象;
(2)常量引用被转化为非常量引用,且仍指向原对象;
注1:不能对非指针或非引用的变量使用
const_cast操作符
,用于移除const
属性。否则编译器报错:const_cast中的类型必须是指针、引用或指向对象类型成员的指针
。
注2:int
类型的变量存储在栈区;const int
类型的变量存储在符号表。
示例:指针或引用的常量类型转换
#include <iostream>
using namespace std;
//常量指针与非常量指针的转换
void func1() {
//常量指针→非常量指针
const int* cp = NULL;
int* p = const_cast<int*>(cp);
//非常量指针→常量指针
char* q = NULL;
const char* cq = const_cast<const char*>(q);
}
//常量引用与非常量引用的转换
void func2() {
//常量引用 → 非常量引用
const int& ca = 1;
int& a = const_cast<int&>(ca);
//非常量引用 → 常量引用
char ch = 'x';
char &b = ch;
const char& cb = const_cast<const char&>(b);
}
//const_cast不能用于非指针和非引用的转换
void func3() {
int a = 10;
//报错:const_cast 中的类型必须是指针、引用或指向对象类型成员的指针
//const int ca = const_cast<const int>(a); //转换失败
}
4 重新解释转换(reinterpret_cast)
重新解释转换reinterpret_cast
是最灵活且最不安全的类型转换机制,容易产生安全问题,不建议使用。
作用:将一种数据类型转换为另一种数据类型,如整型转换为指针类型、自定义数据类型指针转换为非关联类指针。
示例:
#include <iostream>
using namespace std;
void func1() {
//整数 → 指针
int a = 10;
int* p = reinterpret_cast<int*>(a);
}
class Father {
};
class Son : public Father {
};
class Other {
}; //非关联类
void func2() {
//整型 → 非关联类指针
int a = 10;
Other* p1 = reinterpret_cast<Other*>(a);
//自定义数据类型指针 → 非关联类指针
Father *father = NULL;
Other* p2 = reinterpret_cast<Other*>(father);
}
5 类型转换总结
转换机制 | 作用 | 安全性 |
---|---|---|
静态类型转换static_cast |
①内置基本数据类型的转换 ②父子类指针或引用的转换:向上转换、向下转换 |
较不安全:向下转换 |
动态类型转换dynamic_cast |
父子类指针或引用的转换:多态调用、向上转换 | 安全 |
常量类型转换const_cast |
仅适用于修改指针或引用类型的const 属性:常量类型与非常量类型转换 |
/ |
重新解释转换reinterpret_cast |
将一种数据类型转换为另一种数据类型,最灵活且最不安全 | 不安全 |