当前位置: 首页 > article >正文

C++小碗菜之七:类型转换

“这里面也有风风雨雨,有时多云,有时甚至乌云密布,有时也会多云转晴。”     ——2000年8月15日接受华莱士专访时谈中美关系

目录

前言

隐式类型转换

例子

显式类型转换

C风格的类型转换

例子

C++风格的类型转换

static_cast 静态转换

1. 内置数据类型之间的转换

2. 指针或引用的上行转换(从派生类到基类)

dynamic_cast 动态转换

1.指针的下行转换

2.引用的下行转换

const_cast

reinterpret_cast

类型转换的最佳实践

结束语


总阅读时间约为 15~20分钟。

前言

在C++中,类型转换是将一种数据类型的值转换为另一种数据类型的过程。C++提供了多种类型转换方式,包括隐式类型转换显式类型转换。显式类型转换又分为 C风格的类型转换和 C++引入的四种新的类型转换操作符。

隐式类型转换

隐式类型转换是由编译器自动完成的,通常发生在赋值、表达式计算或函数调用时。

例子

#include <iostream>



void printDouble(double value) {

    std::cout << "Value: " << value << std::endl;

}



int main() {

    // 场景 1: 赋值时的隐式转换

    double a = 10.1;       // a 是 double 类型

    int b = a;     // 将 double 隐式转换为 int

    std::cout << "b (int): " << b << std::endl;



    // 场景 2: 表达式计算中的隐式转换

    double c = 3.14;

    int d = 2;

    auto result = c + d;  // 将 int 隐式转换为 double,然后进行加法运算

    std::cout << "Result (double): " << result << std::endl;



    // 场景 3: 函数调用时的隐式转换

    printDouble(b);  // 将 int 隐式转换为 double,传递给函数



    return 0;

}

显式类型转换

C风格的类型转换

C风格的显式类型转换使用 (type)value 的语法,没有类型方面的检查,直接进行强制转换。

例子

double a = 3.14;

int b = (int)a;  // 将 double 转换为 int

C++风格的类型转换

C++引入了四种新的类型转换操作符,提供了更安全和明确的类型转换方式。

static_cast、dynamic_cast、const_cast、reinterpret_cast

static_cast 静态转换

1. 内置数据类型之间的转换

static_cast 可以用于将一种内置数据类型转换为另一种内置数据类型。这种转换在编译时完成,且会进行类型检查

#include <iostream>



int main() {

    double a = 3.14;



    // 将 double 转换为 int

    int b = static_cast<int>(a);



    std::cout << "a (double): " << a << std::endl;

    std::cout << "b (int): " << b << std::endl;



    return 0;

}
2. 指针或引用的上行转换(从派生类到基类)

static_cast 可以用于将派生类指针或引用转换为基类指针或引用。这种转换是安全的,因为派生类对象包含基类子对象。

#include <iostream>



class Base {

public:

    void foo() {

        std::cout << "Base::foo()" << std::endl;

    }

};



class Derived : public Base {

public:

    void bar() {

        std::cout << "Derived::bar()" << std::endl;

    }

};



int main() {

    Derived derivedObj;



    // 将 Derived* 转换为 Base*(上行转换)

    Base* basePtr = static_cast<Base*>(&derivedObj);

    basePtr->foo();  // 调用基类方法



    // 将 Derived& 转换为 Base&(上行转换)

    Base& baseRef = static_cast<Base&>(derivedObj);

    baseRef.foo();  // 调用基类方法



    return 0;

}

dynamic_cast 动态转换

dynamic_cast 是C++中用于处理多态类型之间转换的类型转换操作符。它主要用于在运行将基类指针或引用转换为派生类指针或引用,并在转换失败时提供安全的处理机制(返回 nullptr 或抛出异常)。

1.指针的下行转换
#include <iostream>

#include <typeinfo>



class Base {

public:

    virtual ~Base() = default;  

};



class Derived : public Base {

public:

    void foo() {

        std::cout << "Derived::foo()" << std::endl;

    }

};



int main() {

    Base* basePtr = new Derived;



    // 将 Base* 转换为 Derived*

    Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);

    if (derivedPtr) {

        derivedPtr->foo();  // 调用派生类方法

    } else {

        std::cout << "Conversion failed!" << std::endl;

    }



    delete basePtr;

    return 0;

}
2.引用的下行转换
#include <iostream>

#include <typeinfo>



class Base {

public:

    virtual ~Base() = default;  // 基类必须有虚函数

};



class Derived : public Base {

public:

    void foo() {

        std::cout << "Derived::foo()" << std::endl;

    }

};



int main() {

    Derived derivedObj;

    Base& baseRef = derivedObj;



    try {

        // 将 Base& 转换为 Derived&

        Derived& derivedRef = dynamic_cast<Derived&>(baseRef);

        derivedRef.foo();  // 调用派生类方法

    } catch (const std::bad_cast& e) {

        std::cout << "Conversion failed: " << e.what() << std::endl;

    }



    return 0;

}

const_cast

const_cast用于去除指针或者引用的const属性,在编译的时候会进行类型转换的检查。

#include <iostream>



int main() {

    const int a = 10;

    //int b = const_cast<int>(a); // 这行代码是错误的,因为不能对常量a进行const_cast,这时候应该用static_cast

   

    const int* c = &a;

    int* d = const_cast<int*>(c); // c是指向常量a的指针,可以用const_cast去除const属性



    *d = 20; // 修改d指针指向的内容,这是未定义行为,因为a是常量



    std::cout << "a: " << a << std::endl; // 输出a的值

    std::cout << "*d: " << *d << std::endl; // 输出d指针指向的内容

    return 0;

}

注意,如果本来定义就是一个常量,如果使用 const_cast 强制去掉了常量性质,并往里面写值,这是一种未定义行为(比如在上面的例子中可以加入断点查看a的值以及打印的值),尽量避免以产生无法预料的后果。

除非它原来不是常量,后来被变为常量,然后再用 const_cast 给他变回非常量,这时候可以往里面写值(实际尽量避免使用const_cast去除常量属性)。

reinterpret_cast

是C++中用于低级别类型转换的类型转换操作符。它可以将一种类型的指针、引用或整数转换为另一种类型的指针、引用或整数,而不进行任何类型检查。由于它的行为非常底层且不安全,因此使用reinterpret_cast会非常危险。

类型转换的最佳实践

避免使用C风格的类型转换:C风格的类型转换缺乏类型检查,容易导致未定义行为,如果在C++编程中实在需要使用类型转换,优先使用C++风格的类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast ,这些转换提供了更明确的语义和更好的安全性。

谨慎使用 const_cast:修改常量对象的值可能导致未定义行为。

避免滥用 reinterpret_cast:reinterpret_cast 是低级别的类型转换,通常用于特定场景(如硬件编程)。

注意隐式类型转换的潜在问题:隐式类型转换可能导致精度丢失或意外行为,使用 explicit 关键字可以避免不必要的隐式转换。

结束语

类型转换是C++编程中的一个重要主题,理解并正确使用各种类型转换方式,可以帮助我们编写出更加高效、安全的代码。隐式类型转换虽然方便,但可能导致精度丢失或意外行为;显式类型转换则提供了更明确的语义和更好的安全性,尤其是在使用C++风格的类型转换操作符时。


http://www.kler.cn/a/467166.html

相关文章:

  • 用公网服务代理到本地电脑笔记
  • Android12 App窗口创建流程
  • SpringBoot+Vue养老院管理系统设计与实现【开题报告+程序+安装部署+售后讲解】
  • 3D Object Detection和6D Pose Estimation有什么异同?
  • 『SQLite』创建、附加、分离、备份及恢复数据库
  • Science Robotics让软机器人“活”得更久的3D打印!
  • 适配器模式详解
  • ABAP 两个内表不同名称字段赋值的方法
  • Day30:break语句
  • 《Vue3实战教程》42:Vue3TypeScript 与组合式 API
  • Python爬虫 - 豆瓣图书数据爬取、处理与存储
  • creating-custom-commands-in-flask
  • ubuntu 使用s3fs配置自动挂载对象存储
  • 谷歌2025年AI战略与产品线布局
  • openwrt host方式编译ffmpeg尝试及问题分析
  • 青少年编程与数学 02-006 前端开发框架VUE 02课题、创建工程
  • LeetCode -Hot100 - 53. 最大子数组和
  • 什么是护网行动?
  • spring cloud微服务分布式架构
  • vllm源码(一)
  • jQuery Mobile 可折叠块
  • 51单片机——LED模块
  • NS4863 500mA 锂电池充放电管理IC
  • LeetCode算法题——有序数组的平方
  • UGUI 优化DrawCall操作记录(基于Unity2021.3.18)
  • 049_小驰私房菜_MTK Camera debug,通过adb 命令读写Camera sensor寄存器地址的值