• 隐式类型转换就是编译器自动转;

  • 显式类型转换类如 (char)

# 强制类型转换运算符

MSDN 强制转换运算符 (opens new window)
C++ 强制转换运算符| 菜鸟教程 (opens new window)

C 存在隐式转换和显式转换。C++ 的隐式转换和 C 相同,而把 C 的非常笼统且不安全的显式转换细分为了四种显式转换,如下。

# reinterpret_cast

字面意思是按位“重新解释”,可以实现 指针另一种指针/整数 的互相转换。

int * int_ptr = new int;
char * char_ptr = reinterpret_cast<char*> int_ptr;

# const_cast

能(且只能)为变量加上或删除 constvolatile__unaligned 特性。

但需要注意的是,const_cast 修改使用 const 创建的变量是未定义行为。原因是,如果在创建变量时使用 const int,编译器可以进行优化,修改这种变量是未定义行为(详见 cv 限定符 部分)。

void square(const int* px) {
    int* p = const_cast<int*>(px);  // const_cast 去掉了 px 的 const volatile 限制
    *p = (*p) * (*p);
}
int main() {
    int i = 5;                  // 创建变量时使用 const
    const int ci = 5;           // 创建变量时使用 const
    const int* pi = new int(5); // 创建变量时不使用 const

    square(&i);
    square(&ci); // 未定义行为
    square(pi);

    cout << i << " " << ci << " " << *pi;
    // 在 g++ 和 msvc 中均输出 25 5 25
    // 但 VS 调试器显示 ci 对应内存的值为 25,显然是 cout 语句被编译器优化了
    return 0;
}

如果定义为 const volatile 阻止编译器优化,修改这种变量是合法的。

void square(const volatile int* px) {
    int* p = const_cast<int*>(px);  // const_cast 去掉了 px 的 const volatile 限制
    *p = (*p) * (*p);
}
int main() {
    int i = 5;
    const int ci = 5;
    const volatile int cvi = 5; // 使用 volatile 阻止编译器优化

    square(&i);
    square(&ci); // 未定义行为
    square(&cvi);

    cout << i << " " << ci << " " << cvi;
    // 在 g++ 和 msvc 中均输出 25 5 25
    return 0;
}

# static_cast

static_cast<int> 类似于 C 的显式转换,可用于父类向派生类转换、intchar 转换等。这些报错都是在编译阶段完成。

float f = 2.33;
int i = static_cast<int>(f); // 合法
struct A {};
struct B: public A {};

int main() {
    A a;
    B* b = static_cast<B*>(&a); // 合法
    return 0;
}

但是不同的是,显式转换是真的什么都可以转,而 static_cast 还是做了一些限制的,比如不能做 const_cast reinterpret_cast 以及不相关的类型转换。

struct A {};
struct B {};

int main() {
    A a;
    B* b1 = (B*)&a;                 // 不报错
    B* b2 = static_cast<B*>(&a);    // 报错
    int i1 = (int)&a;               // 不报错
    int i2 = static_cast<int>(&a);  // 报错
    return 0;
}

# dynamic_cast

  1. 用于多态类型的转换
  2. 执行行运行时类型检查
  3. 只适用于指针或引用
  • 对不明确的指针的转换将失败(返回 nullptr),但不引发异常
  • 对不明确的引用的转换将抛出 bad_cast 异常
  1. 可以在整个类层次结构中移动指针,包括向上转换、向下转换

# bad_cast 异常

  • 由于强制转换为引用类型失败,dynamic_cast 运算符引发 bad_cast 异常。