第十六章、类型转换

关于数据类型转换 在 C 语言中只有两种类型转换模式:隐式类型转换(编译器默认)和强制类型转换(使用() 运算符手动转换).

在 C++ 语言中,隐式类型转换依旧保留,但不建议使用强制类型转换。

由于 C++ 的结构体和类会存在虚表指针等问题。因此 C 语言的强制类型转换可能会带来不可预测的结果。所以 C++ 语言提供了四种比较安全且语义明确的类型转换方法。

C++ 中的类型转换

  1. 静态转换:static_cast
  2. 动态转换:dynamic_cast
  3. 常量转换:const_cast
  4. 重解释转换:reinterpret_cast

1. 静态转换

静态转换(static_cast编译时对已知类型进行确定性的类型转换。

可以用与静态转换的场景有:

  1. 基本数据类型的转换,如:intfloat
  2. 具有继承关系的类的指针或引用的转换,通常是向父类方向转换时安全的。也允许向子类方向转换,但开发者自担风险。
  3. void* 类型的指针转换为具体类型的指针。

静态转换失败(编译报错)的情况有:

  1. 无关类型转换(无关指针和无关引用)
  2. 移除 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)