C++中的类型转换(Type Conversion)是指将一个数据类型的值转换为另一个数据类型的过程,主要包括:
一、算术类型转换(Arithmetic Conversions)
算术类型转换通常发生在算术运算或比较中 ,称为**"标准转换"(standard conversion),遵循一定的提升规则(promotion rules)**。
转换规则(简化版):
bool
→int
- 整型提升:
char
、short
→int
- 两个操作数不同类型时:
- 若一个为浮点型,另一个为整型 → 整型转换为浮点型
- 若一个为
double
,另一个为float
→float
转为double
- 若一个为
unsigned
且它的值不能用int
表示 →int
转为unsigned
- 否则,
unsigned
提升优先级高于signed
示例:
cpp
#include <iostream>
int main() {
char c = 100;
int i = 200;
float f = 1.5f;
double d = 3.14;
auto result1 = c + i; // char → int,结果是 int
auto result2 = i + f; // int → float,结果是 float
auto result3 = f + d; // float → double,结果是 double
std::cout << "result1: " << result1 << "\n"; // 300
std::cout << "result2: " << result2 << "\n"; // 201.5
std::cout << "result3: " << result3 << "\n"; // 4.64
}
二、其他隐式类型转换(Implicit Conversion)
这是 编译器自动完成 的转换,也叫类型提升(promotion)或类型协同(coercion)。
常见的隐式转换:
类型 | 转换方向 | 示例 |
---|---|---|
数值型 | 更大/更精度的数值 | int → double |
指针类型 | 派生类 → 基类 | Derived* → Base* |
空指针 | nullptr → 任何指针类型 |
nullptr → int* |
数组/函数 → 指针 | int arr[] → int* |
示例:
cpp
void printDouble(double d) {
std::cout << "Double: " << d << "\n";
}
class Base {};
class Derived : public Base {};
int main() {
int i = 42;
printDouble(i); // int → double(隐式)
Derived d;
Base* bptr = &d; // Derived* → Base*(隐式)
}
三、显示类型转换(Explicit Conversion / Cast)
你可以显式地指示编译器进行类型转换,有四种标准C++风格的转换方式(推荐),以及一个C风格的转换(不推荐)。
四种C++显式转换:
-
static_cast<T>(expr)
➤ 用于基本类型之间转换 、指针/引用向上转换等安全转换。
-
dynamic_cast<T>(expr)
➤ 用于带有虚函数的多态类 之间的安全运行时类型检查和向下转换。
-
const_cast<T>(expr)
➤ 添加或去除const、volatile限定符,常用于函数参数处理。
-
reinterpret_cast<T>(expr)
➤ 不安全但允许的位级别转换,如指针与整数之间转换。
-
(T)expr
------ C风格强制转换➤ 组合了上述所有功能,不安全不透明,不推荐使用。
示例:
cpp
#include <iostream>
class Base { public: virtual ~Base() {} };
class Derived : public Base { public: void say() { std::cout << "Derived\n"; } };
int main() {
int i = 100;
double d = static_cast<double>(i); // int → double
Base* b = new Derived();
Derived* dptr = dynamic_cast<Derived*>(b); // 安全向下转型
if (dptr) dptr->say();
const int ci = 42;
int* p = const_cast<int*>(&ci); // 去除 const 限定
void* vptr = reinterpret_cast<void*>(p); // int* → void*
int* iptr = reinterpret_cast<int*>(vptr); // void* → int*
delete b;
}
四、总结对比表:
转换类型 | 触发方式 | 安全性 | 用途/说明 |
---|---|---|---|
算术转换 | 自动 | 安全 | 数值运算中的标准提升 |
隐式转换 | 自动 | 通常安全 | 函数调用/指针/基本类型提升 |
static_cast |
显式 | 安全 | 编译期可检查的转换,如 int→float,向上转型 |
dynamic_cast |
显式 | 安全 | 多态类型的运行时向下转型 |
const_cast |
显式 | 有风险 | 去除 const/volatile |
reinterpret_cast |
显式 | 不安全 | 位级别转换,极端情况用 |
C风格强制转换 | 显式 | 不推荐 | 混合多个C++转换,缺乏类型安全 |
五、综合例子
下面是一个C++ 示例工程,通过一个模拟图形系统的类结构,演示了**各种类型转换(隐式、算术、显示转换)**的组合使用。代码里有注释,方便理解每一种转换在什么时候触发、为什么安全或者不安全。
定义 shape.h
图形类头文件内容如下:
cpp
#pragma once
#include <iostream>
#include <string>
class Shape {
public:
virtual ~Shape() {}
virtual void draw() const;
};
class Circle : public Shape {
public:
Circle(double r);
void draw() const override;
double getRadius() const;
private:
double radius;
};
class Rectangle : public Shape {
public:
Rectangle(int w, int h);
void draw() const override;
int area() const;
private:
int width, height;
};
// 模拟图形渲染系统的底层资源对象
struct RenderHandle {
void* data;
};
RenderHandle createHandle(int id);
shape.cpp
图形类实现如下:
cpp
#include "shape.h"
void Shape::draw() const {
std::cout << "Drawing Shape\n";
}
Circle::Circle(double r) : radius(r) {}
void Circle::draw() const {
std::cout << "Drawing Circle with radius: " << radius << "\n";
}
double Circle::getRadius() const {
return radius;
}
Rectangle::Rectangle(int w, int h) : width(w), height(h) {}
void Rectangle::draw() const {
std::cout << "Drawing Rectangle of area: " << area() << "\n";
}
int Rectangle::area() const {
return width * height;
}
RenderHandle createHandle(int id) {
RenderHandle h;
h.data = reinterpret_cast<void*>(id); // 显式 reinterpret_cast
return h;
}
main.cpp
主函数演示各种类型转换示例内容如下:
cpp
#include "shape.h"
#include <typeinfo>
void printDouble(double d) {
std::cout << "Double value: " << d << "\n";
}
int main() {
// 算术类型转换(int → double)
int i = 42;
double d = i; // 隐式转换
printDouble(d); // 参数是 double
float f = static_cast<float>(i); // 显式 static_cast
std::cout << "Float from int: " << f << "\n";
// 基类 → 派生类的动态转换(dynamic_cast)
Shape* s = new Circle(3.5);
s->draw();
if (Circle* c = dynamic_cast<Circle*>(s)) {
std::cout << "Radius from casted circle: " << c->getRadius() << "\n";
}
// const_cast 演示
const int ci = 100;
int* modifiable = const_cast<int*>(&ci);
*modifiable = 999; // 未定义行为,仅演示用
std::cout << "Modified const int (unsafe!): " << *modifiable << "\n";
// reinterpret_cast 演示
int resourceID = 1234;
RenderHandle h = createHandle(resourceID);
int recoveredID = reinterpret_cast<int>(h.data);
std::cout << "Recovered ID from RenderHandle: " << recoveredID << "\n";
// 隐式派生 → 基类(安全)
Rectangle rect(10, 20);
Shape* s2 = ▭
s2->draw(); // 虚函数,多态行为
delete s;
return 0;
}
示例的演示内容如下:
场景 | 类型转换 | 涉及关键字/方式 |
---|---|---|
int → double |
算术隐式转换 | 自动 |
float ← int |
算术显式转换 | static_cast |
Base* ← Derived* |
隐式向上转换 | 自动 |
Derived* ← Base* |
安全运行时转换 | dynamic_cast |
const int* ← int* |
添加/去除 const | const_cast |
void* ←→ int |
指针/整数转换 | reinterpret_cast |
Shape 多态行为 |
虚函数机制 | 隐式 |