第十六章、类型转换
关于数据类型转换 在 C 语言中只有两种类型转换模式:隐式类型转换(编译器默认)和强制类型转换(使用() 运算符手动转换).
在 C++ 语言中,隐式类型转换依旧保留,但不建议使用强制类型转换。
由于 C++ 的结构体和类会存在虚表指针等问题。因此 C 语言的强制类型转换可能会带来不可预测的结果。所以 C++ 语言提供了四种比较安全且语义明确的类型转换方法。
C++ 中的类型转换
- 静态转换:
static_cast。 - 动态转换:
dynamic_cast。 - 常量转换:
const_cast。 - 重解释转换:
reinterpret_cast。
1. 静态转换
静态转换(static_cast) 是编译时对已知类型进行确定性的类型转换。
可以用与静态转换的场景有:
- 基本数据类型的转换,如:
int转float。 - 具有继承关系的类的指针或引用的转换,通常是向父类方向转换时安全的。也允许向子类方向转换,但开发者自担风险。
- 将
void*类型的指针转换为具体类型的指针。
静态转换失败(编译报错)的情况有:
- 无关类型转换(无关指针和无关引用)
- 移除 const 属性
语法
static_cast<新类型>(表达式)
示例
// filename: static_cast.cpp
#include <iostream>
using namespace std;
class Point {
public:
Point(float ax=0, float ay=0):x(ax), y(ay) { }
void info(void) {
cout << "点(" << x << "," << y << ")\n";
}
public:
float x;
float y;
};
class Circle : public Point {
public:
Circle(float ax, float ay, float radius)
: Point(ax, ay), r(radius) { }
void info(void) { // 子类的此函数也为虚函数
cout << "圆(" << x << "," << y << "," << r << ")\n";
}
public:
float r; // 半径
};
int main(int argc, char * argv[]) {
int x;
float y = 3.14;
x = static_cast<int>(y);
cout << "x:" << x << endl;
Point p1(1, 2);
Circle c1(3, 4, 5);
Point * pp;
Circle *pc;
pp = static_cast<Point*>(&c1);
pp->info();
// 可以类型转换,但运行时出错
pc = static_cast<Circle*>(&p1);
pc->info(); // 运行结果有错。
Point & rp = static_cast<Point&>(c1);
rp.info();
// 可以类型转换,但运行时出错
Circle & rc = static_cast<Circle&>(p1);
rc.info(); // 运行结果有错。
// x = static_cast<int>(p1); // 报错:无关类型转换
// const int z = 666;
// int *pz = static_cast<int*>(&z); // 报错:不能去除const 属性
return 0;
}
编译和运行运行结果如下:
weimz@mzstudio:~/old$ g++ -o static_cast static_cast.cpp
weimz@mzstudio:~/old$ ./static_cast
x:3
点(3,4)
圆(1,2,3)
点(3,4)
圆(1,2,3)