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

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

强制类型转换运算符

MSDN 强制转换运算符
C++ 强制转换运算符| 菜鸟教程

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

reinterpret_cast

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

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

const_cast

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 阻止编译器优化,修改这种变量是合法的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 转换等。这些报错都是在编译阶段完成。

1
2
float f = 2.33;
int i = static_cast<int>(f); // 合法
1
2
3
4
5
6
7
8
struct A {};
struct B: public A {};

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

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

1
2
3
4
5
6
7
8
9
10
11
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 异常
  4. 可以在整个类层次结构中移动指针,包括向上转换、向下转换

bad_cast 异常

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