C++中的算术转换、其他隐式范例转换和显示转换详解

[复制链接]
发表于 2025-9-22 07:18:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
C++中的范例转换(Type Conversion)是指将一个数据范例的值转换为另一个数据范例的过程,重要包罗:

一、算术范例转换(Arithmetic Conversions)

算术范例转换通常发生在算术运算或比力中,称为**“标准转换”(standard conversion),遵照一定的提升规则(promotion rules)**。
转换规则(简化版):


  • bool → int
  • 整型提升:char、short → int
  • 两个操纵数差别范例时:

    • 若一个为浮点型,另一个为整型 → 整型转换为浮点型
    • 若一个为double,另一个为float → float 转为 double
    • 若一个为unsigned且它的值不能用int体现 → int转为unsigned
    • 否则,unsigned提升优先级高于signed

示例:
  1. #include <iostream>
  2. int main() {
  3.     char c = 100;
  4.     int i = 200;
  5.     float f = 1.5f;
  6.     double d = 3.14;
  7.     auto result1 = c + i;   // char → int,结果是 int
  8.     auto result2 = i + f;   // int → float,结果是 float
  9.     auto result3 = f + d;   // float → double,结果是 double
  10.     std::cout << "result1: " << result1 << "\n"; // 300
  11.     std::cout << "result2: " << result2 << "\n"; // 201.5
  12.     std::cout << "result3: " << result3 << "\n"; // 4.64
  13. }
复制代码

二、其他隐式范例转换(Implicit Conversion)

这是 编译器主动完成 的转换,也叫范例提升(promotion)或范例协同(coercion)。
常见的隐式转换:

范例转换方向示例数值型更大/更精度的数值int → double指针范例派生类 → 基类Derived* → Base*空指针nullptr → 任何指针范例nullptr → int*数组/函数 → 指针int arr[] → int*示例:
  1. void printDouble(double d) {
  2.     std::cout << "Double: " << d << "\n";
  3. }
  4. class Base {};
  5. class Derived : public Base {};
  6. int main() {
  7.     int i = 42;
  8.     printDouble(i); // int → double(隐式)
  9.     Derived d;
  10.     Base* bptr = &d; // Derived* → Base*(隐式)
  11. }
复制代码

三、显示范例转换(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风格欺压转换
    ➤ 组合了上述全部功能,不安全不透明,不保举使用。

示例:
  1. #include <iostream>
  2. class Base { public: virtual ~Base() {} };
  3. class Derived : public Base { public: void say() { std::cout << "Derived\n"; } };
  4. int main() {
  5.     int i = 100;
  6.     double d = static_cast<double>(i);  // int → double
  7.     Base* b = new Derived();
  8.     Derived* dptr = dynamic_cast<Derived*>(b);  // 安全向下转型
  9.     if (dptr) dptr->say();
  10.     const int ci = 42;
  11.     int* p = const_cast<int*>(&ci);  // 去除 const 限定
  12.     void* vptr = reinterpret_cast<void*>(p); // int* → void*
  13.     int* iptr = reinterpret_cast<int*>(vptr); // void* → int*
  14.     delete b;
  15. }
复制代码

四、总结对比表:

转换范例触发方式安全性用途/阐明算术转换主动安全数值运算中的标准提升隐式转换主动通常安全函数调用/指针/根本范例提升static_cast显式安全编译期可查抄的转换,如 int→float,向上转型dynamic_cast显式安全多态范例的运行时向下转型const_cast显式有风险去除 const/volatilereinterpret_cast显式不安全位级别转换,极度环境用C风格欺压转换显式不保举混合多个C++转换,缺乏范例安全五、综合例子

下面是一个C++ 示例工程,通过一个模仿图形系统的类结构,演示了**各种范例转换(隐式、算术、显示转换)**的组合使用。代码里有表明,方便理解每一种转换在什么时候触发、为什么安全大概不安全。
界说 shape.h图形类头文件内容如下:
  1. #pragma once
  2. #include <iostream>
  3. #include <string>
  4. class Shape {
  5. public:
  6.     virtual ~Shape() {}
  7.     virtual void draw() const;
  8. };
  9. class Circle : public Shape {
  10. public:
  11.     Circle(double r);
  12.     void draw() const override;
  13.     double getRadius() const;
  14. private:
  15.     double radius;
  16. };
  17. class Rectangle : public Shape {
  18. public:
  19.     Rectangle(int w, int h);
  20.     void draw() const override;
  21.     int area() const;
  22. private:
  23.     int width, height;
  24. };
  25. // 模拟图形渲染系统的底层资源对象
  26. struct RenderHandle {
  27.     void* data;
  28. };
  29. RenderHandle createHandle(int id);
复制代码

shape.cpp 图形类实现如下:
  1. #include "shape.h"
  2. void Shape::draw() const {
  3.     std::cout << "Drawing Shape\n";
  4. }
  5. Circle::Circle(double r) : radius(r) {}
  6. void Circle::draw() const {
  7.     std::cout << "Drawing Circle with radius: " << radius << "\n";
  8. }
  9. double Circle::getRadius() const {
  10.     return radius;
  11. }
  12. Rectangle::Rectangle(int w, int h) : width(w), height(h) {}
  13. void Rectangle::draw() const {
  14.     std::cout << "Drawing Rectangle of area: " << area() << "\n";
  15. }
  16. int Rectangle::area() const {
  17.     return width * height;
  18. }
  19. RenderHandle createHandle(int id) {
  20.     RenderHandle h;
  21.     h.data = reinterpret_cast<void*>(id);  // 显式 reinterpret_cast
  22.     return h;
  23. }
复制代码
main.cpp 主函数演示各种范例转换示例内容如下:
  1. #include "shape.h"
  2. #include <typeinfo>
  3. void printDouble(double d) {
  4.     std::cout << "Double value: " << d << "\n";
  5. }
  6. int main() {
  7.     // 算术类型转换(int → double)
  8.     int i = 42;
  9.     double d = i; // 隐式转换
  10.     printDouble(d); // 参数是 double
  11.     float f = static_cast<float>(i); // 显式 static_cast
  12.     std::cout << "Float from int: " << f << "\n";
  13.     // 基类 → 派生类的动态转换(dynamic_cast)
  14.     Shape* s = new Circle(3.5);
  15.     s->draw();
  16.     if (Circle* c = dynamic_cast<Circle*>(s)) {
  17.         std::cout << "Radius from casted circle: " << c->getRadius() << "\n";
  18.     }
  19.     // const_cast 演示
  20.     const int ci = 100;
  21.     int* modifiable = const_cast<int*>(&ci);
  22.     *modifiable = 999; // 未定义行为,仅演示用
  23.     std::cout << "Modified const int (unsafe!): " << *modifiable << "\n";
  24.     // reinterpret_cast 演示
  25.     int resourceID = 1234;
  26.     RenderHandle h = createHandle(resourceID);
  27.     int recoveredID = reinterpret_cast<int>(h.data);
  28.     std::cout << "Recovered ID from RenderHandle: " << recoveredID << "\n";
  29.     // 隐式派生 → 基类(安全)
  30.     Rectangle rect(10, 20);
  31.     Shape* s2 = &rect;
  32.     s2->draw();  // 虚函数,多态行为
  33.     delete s;
  34.     return 0;
  35. }
复制代码
示例的演示内容如下:

场景范例转换涉及关键字/方式int → double算术隐式转换主动float ← int算术显式转换static_castBase* ← Derived*隐式向上转换主动Derived* ← Base*安全运行时转换dynamic_castconst int* ← int*添加/去除 constconst_castvoid* ←→ int指针/整数转换reinterpret_castShape 多态活动虚函数机制隐式
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表