C++: 隐式类型转换和显式类型转换

【C++】类的隐式类型转换 C++ 类的隐式类型转换是指当一个类定义了适当的构造函数或转换函数时,可以在需要时自动进行类型转换,而无需显式调用转换函数或构造函数。这使得代码更具灵活性和简洁性。下面是一些关于类的隐式类型转换的示例:public:MyString(const char* str) : data(str) {} // 构造函数,将 const char* 转换为 MyStringprivate:// 隐式类型转换:const char* 转换为 MyString// 输出 "Hello, World! 阅读详情

 

第1部分. 隐式类型转换


又称为“标准转换”,包括以下几种情况:
1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。

int ival = 3;
double dval = 3.14159;

ival + dval;//ival被提升为double类型

2)一种类型表达式赋值给另一种类型的对象:目标类型是被赋值对象的类型

int *pi = 0; // 0被转化为int *类型
ival = dval; // double->int

例外:void指针赋值给其他指定类型指针时,不存在标准转换,编译出错

3)将一个表达式作为实参传递给函数调用,此时形参和实参类型不一致:目标转换类型为形参的类型

extern double sqrt(double);

cout << "The square root of 2 is " << sqrt(2) << endl;
//2被提升为double类型:2.0

4)从一个函数返回一个表达式,表达式类型与返回类型不一致:目标转换类型为函数的返回类型

double difference(int ival1, int ival2)
{
    return ival1 - ival2;
    //返回值被提升为double类型
}

 

第2部分. 显式类型转换


被称为“强制类型转换”(cast)
C     风格: (type-id)
C++风格: static_cast、dynamic_cast、reinterpret_cast、和const_cast..

 

关于强制类型转换的问题,很多书都讨论过,写的最详细的是C++ 之父的《C++ 的设计和演化》。最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_cast, dynamic_cast。标准C++中有四个类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。下面对它们一一进行介绍。
 

static_cast

 

用法:static_cast < type-id > ( expression )

 

说明:该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。

 

来源:为什么需要static_cast强制转换?
情况1:void指针->其他类型指针
情况2:改变通常的标准转换
情况3:避免出现可能多种转换的歧义




它主要有如下几种用法:
  • 用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类指针或引用)时,由于没有动态类型检查,所以是不安全的。
  • 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
  • 把void指针转换成目标类型的指针(不安全!!)
  • 把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volitale、或者__unaligned属性。
 

dynamic_cast

 

用法:dynamic_cast < type-id > ( expression )

 

说明:该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。


来源:为什么需要dynamic_cast强制转换?
简单的说,当无法使用virtual函数的时候

典型案例:
Wicrosoft公司提供给我们一个类库,其中提供一个类Employee.以头文件Eemployee.h和类库.lib分发给用户
显然我们并无法得到类的实现的源代码
//Emplyee.h
class Employee 
{
public:
    virtual int salary();
};

class Manager : public Employee
{
public: 
    int salary();
};

class Programmer : public Employee
{
public:
    int salary();
};

我们公司在开发的时候建立有如下类:
class MyCompany
{
public:
    void payroll(Employee *pe);
    //
};

void MyCompany::payroll(Employee *pe)
{
    //do something
}

但是开发到后期,我们希望能增加一个bonus()的成员函数到W$公司提供的类层次中。
假设我们知道源代码的情况下,很简单,增加虚函数:
//Emplyee.h
class Employee 
{
public:
    virtual int salary();
    virtual int bonus();
};

class Manager : public Employee
{
public: 
    int salary();
};

class Programmer : public Employee
{
public:
    int salary();
    int bonus();
};

//Emplyee.cpp

int Programmer::bonus()
{
    //
}


payroll()通过多态来调用bonus()
class MyCompany
{
public:
    void payroll(Employee *pe);
    //
};

void MyCompany::payroll(Employee *pe)
{
    //do something
    //pe->bonus();
}

但是现在情况是,我们并不能修改源代码,怎么办?dynamic_cast华丽登场了!
在Employee.h中增加bonus()声明,在另一个地方定义此函数,修改调用函数payroll().重新编译,ok

 

//Emplyee.h
class Employee 
{
public:
    virtual int salary();
};

class Manager : public Employee
{
public: 
    int salary();
};

class Programmer : public Employee
{
public:
    int salary();
    int bonus();//直接在这里扩展
};

//somewhere.cpp

int Programmer::bonus()
{
    //define
}

 
class MyCompany
{
public:
    void payroll(Employee *pe);
    //
};

void MyCompany::payroll(Employee *pe)
{
    Programmer *pm = dynamic_cast<Programmer *>(pe);
    
    //如果pe实际指向一个Programmer对象,dynamic_cast成功,并且开始指向Programmer对象起始处
    if(pm)
    {
        //call Programmer::bonus()
    }
    //如果pe不是实际指向Programmer对象,dynamic_cast失败,并且pm = 0
    else
    {
        //use Employee member functions
    }
}


dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。

在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
class Base
{
public:
    int m_iNum;
    virtual void foo();
};

class Derived:public Base
{
public:
    char *m_szName[100];
};

void func(Base *pb)
{
    Derived *pd1 = static_cast<Derived *>(pb);

    Derived *pd2 = dynamic_cast<Derived *>(pb);
}

在上面的代码段中,
如果pb实际指向一个Derived类型的对象,pd1和pd2是一样的,并且对这两个指针执行Derived类型的任何操作都是安全的;
如果pb实际指向的是一个Base类型的对象,那么pd1将是一个指向该对象的指针,对它进行Derived类型的操作将是不安全的(如访问m_szName),而pd2将是一个空指针(即0,因为dynamic_cast失败)。
另外要注意:Base要有虚函数,否则会编译出错;static_cast则没有这个限制。这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,详细可见<Inside c++ object model>)中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。

另外,dynamic_cast还支持交叉转换(cross cast)。如下代码所示。
class Base
{
public:
    int m_iNum;
    virtual void f(){}
};



class Derived1 : public Base
{

};

class Derived2 : public Base
{

};

void foo()
{
    derived1 *pd1 = new Drived1;

    pd1->m_iNum = 100;

    Derived2 *pd2 = static_cast<Derived2 *>(pd1); //compile error

    Derived2 *pd2 = dynamic_cast<Derived2 *>(pd1); //pd2 is NULL

    delete pd1;
}

在函数foo中,使用static_cast进行转换是不被允许的,将在编译时出错;而使用 dynamic_cast的转换则是允许的,结果是空指针。
 

reinpreter_cast

 

用法:reinpreter_cast<type-id> (expression)

 

说明:type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。



该运算符的用法比较多。
 

const_cast

 

用法:const_cast<type_id> (expression)

 

说明:该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。



常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

Voiatile和const类试。举如下一例:

class B{

public:
int m_iNum;
}

void foo(){
const B b1;
b1.m_iNum = 100; //comile error
B b2 = const_cast<B>(b1);
b2. m_iNum = 200; //fine
}


上面的代码编译时会报错,因为b1是一个常量对象,不能对它进行改变;使用const_cast把它转换成一个常量对象,就可以对它的数据成员任意改变。注意:b1和b2是两个不同的对象。

C语言的显式类型转换和隐式类型转换详细讲解 类型转换主要分为显式类型转换和隐式类型转换。隐式类型转换又分为整型提升和算术转换两个操作。整型提升的用途主要是在表达式中,有数据类型小于int类型大小的,编译器就会隐式的把小于int类型的数据转换为int类型的数据。算术转换的用途就是在表达式中,操作数的数据类型都是大于等于int 类型,并且数据类型不一致,这个时候编译器就会隐式算术转换。 阅读详情

相关推荐

C语言隐式/显式类型转换 | C++四种强制类型转换、类的隐式转换、explicit

文章目录何时发生隐式类型转换 何时发生隐式类型转换 在大多数表达式中,比int类型小的整数值提升为较大的整数类型 在条件中,非布尔值转换成布尔类型 初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转化成左侧运算对象的类型 算术运算或关系运算对象有多种类型,需要转换成同一种类型 函数调用时也会发生类型转换 ...

Jormungand_V的博客 2856

C++隐式类型转换

隐式类型转换针对不同的类型有不同的转换方式,总体可以分为两种类型,算术类型和类类型。 1. 算术类型转换 算术类型转换的设计原则就是尽可能避免损失精度。 具体地,有以下几条参考规则: 整型提升:将小整数类型转换成较大的整数类型。例如,如果一个运算对象的类型是long double,那么另外一个运算对象,无论它的类型是什么,都会被转换成long double。 有符号类型转换为无符号类型。类型转换一般不会改变对象内存的值,当一个有符号类型的对象转换为无符号类型时,其表示出来的值可能发生变化,例如,int a

M2嵌入式 7977

用PyCharm+Scrapy打造你的第一个爬虫:从安装到实战(附完整代码)

本文详细介绍了如何使用PyCharm和Scrapy框架从零开始构建高效网络爬虫。通过环境配置、项目创建、核心爬虫逻辑编写到数据处理与存储的完整流程,帮助Python开发者快速掌握爬虫开发技巧,并附有实战代码示例。特别适合想要学习Scrapy框架和提升爬虫技能的开发者。

weixin_29038345的博客 869

C++类型转换:隐式转换和显式转换

隐式转换 当一个值拷贝给另一个兼容类型的值时,隐式转换会自动进行。所谓隐式转换,是指不需要用户干预,编译器私下进行的类型转换行为。 例如: short a=2000; int b; b=a; 在这里,a在没有任何显示操作符的干预下,由short类型转换为int类型。这就是标准转换,标准转换将影响基本数据类型,并允许数字类型之间的转换(short到int, int到float, double到int…),到bool或从bool,以及一些指针转换。 对于非基本类型,数组和函数隐式地转换为指针,并且指

DayDayUp 2万+

Windows下飞桨PaddlePaddle 2.6.1 GPU版环境搭建全攻略(含CUDA 11.7配置避坑指南)

本文详细介绍了在Windows系统下搭建飞桨PaddlePaddle 2.6.1 GPU版环境的完整流程,特别针对CUDA 11.7和cuDNN的安装提供了避坑指南。从Anaconda环境配置、CUDA Toolkit安装到飞桨GPU版的验证,手把手帮助开发者高效完成深度学习环境搭建,解决常见问题并优化性能。

x8y9z0的博客 1095

零代码搭建专业知识库:Wiki.js+cpolar让团队协作像写笔记一样简单

"项目文档又找不到了!“团队负责人小张第N次在群里看到这样的抱怨——技术文档分散在邮件、网盘和个人电脑里,新人入职要花一周熟悉文档位置,远程协作时版本混乱更是家常便饭。Wiki.js与cpolar内网穿透服务的出现,就像给团队协作装上了"中央大脑”,用写Markdown笔记的简单方式,搭建一个专业的知识库系统。普通人对知识管理的需求其实很简单:方便记录、容易查找、大家能用。但传统方案把这个过程搞得异常复杂:建服务器、配环境、学语法、搞权限……大部分团队还没开始就放弃了。

Yawesh的博客 2040

C++类型转换分为:隐式类型转换和显式类型转换

首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况: 1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。   int ival = 3; double dval = 3.14159;

wtuetnsrmh的专栏 557

从真题到策略:浙江工业大学计算机转专业机试全解析与备考指南

本文全面解析浙江工业大学计算机转专业机试的考试概况、典型真题和高频考点,提供详细的备考策略和面试准备建议。从机试题目类型到解题技巧,帮助考生高效备考,顺利通过这一竞争激烈的转专业关卡。

weixin_42524824的博客 422

C++ 类型转换

隐式类型转换 1 数值类型转换 2 指针类型转换 显式类型转换 1 explicit关键字 1 强制类型转换 11 static_cast 12 dynamic_cast 13 const_cast 14 reinterpret_cast 参考资料 C++类型转换大体上包括隐式类型转换和显式类型转换。1. 隐式类型转换隐式类型转换是自动执行的,无需显式的操作符。 隐式类型转换发生在很多地方,比如函数

shuzfan的专栏 1万+

ADC噪声参数博弈论:为何24位ADC的有效分辨率可能不如16位?

本文深入探讨了ADC噪声参数的核心矛盾,揭示了24位ADC有效分辨率可能不如16位ADC的根本原因。关键在于跳出单纯比较位数的误区,转而关注输入参考噪声这一绝对指标。文章通过分析参考电压对满量程范围和噪声模型的影响,阐述了动态范围与最小可测信号之间的取舍逻辑,为工程师提供了基于系统实际需求的ADC选型与噪声评估框架。

snow3的博客 706

移动端实战指南:深入理解 & 接入 IAB OMSDK

OMSDK(OpenMeasurementSDK)是IABTechLab推出的标准化测量工具,用于统一移动端/原生App广告的可见性和验证流程。其核心包括Native库(采集设备数据)和OMID JavaScript层(实现通信),通过标准化接口让开发者只需接入一套SDK即可兼容多个测量厂商,减少冲突和性能损耗。v1.4版本强化了对CTV和原生App场景的支持,而v1.5新增了画中画检测等功能。集成流程需通过IAB技术实验室注册下载,并遵循严格的命名空间规则。测试阶段需嵌入验证脚本并通过指定工具验证

帅次的博客 1190

C++的类型转换

由于编译器认为const修饰的变量是不会被修改的,因此会将const修饰的变量存放到寄存器当中,当需要读取const变量时就会直接从寄存器中进行读取,而我们修改的实际上是内存中的a的值,因此最终打印出a的值是未修改之前的值。上述代码中,如果传入func函数的是子类对象的地址,那么在转换后pb1和pb2都会有对应的地址,但如果传入func函数的是父类对象的地址,那么转换后pb1会有对应的地址,而pb2则是一个空指针。如果父类的指针(或引用)指向的是一个子类对象,那么将其转换为子类的指针(或引用)则是安全的。

weixin_53831496的博客 1379

【AI产品与商业航图】Flux.1 完全开源 AI 绘图模型:本地部署与 ComfyUI 实战指南

Flux.1是一个开源项目,用户可以自由使用和修改,完全免除使用费用。🖥️本地部署支持:与一些依赖云端计算的工具不同,Flux.1支持本地部署,确保用户可以离线使用并自主控制数据隐私。🔄兼容ComfyUI框架:Flux.1可以无缝集成到ComfyUI中,用户可以享受更加简便和直观的操作界面。🎨卓越的图像生成能力:Flux.1能够生成高质量、细腻的图像,支持多种风格与创作主题的切换。💾低硬件要求。

高校图书馆高级系统架构师/研究馆员,推动高校AI从概念演示到可评审、可交付、可运维:路线图与立项评审、PoC交付、评测回归与上线运维(Baseline/Eval/Ops)。 1738

C++中的4种显示的类型转换

C++支持多种类型的转换,这些转换可以分为两大类:隐式类型转换(Implicit Conversions)和显式类型转换(Explicit Conversions),而显式类型转换又包括四种类型转换运算符。

qinghehe198508的博客 689

OpenCV实例(八)车牌字符识别技术(三)汉字识别

相较于数字和英文字符的识别,汽车牌照中的汉字字符识别的难度更大,主要原因有以下4个方面:(1)字符笔画因切分误差导致非笔画或笔画流失。(2)汽车牌照被污染导致字符上出现污垢。(3)采集所得车辆图像分辨率低导致多笔画的汉字较难分辨。(4)车辆图像采集时所受光照影响的差异导致笔画较淡。综合汉字识别时的这些难点来看,很难被直接提取的是字符的局部特征。笔画作为最重要的特征而仅存在于汉字中,这由先验知识可知。一旦捺、横、竖、撇这些笔画特征被提取到,对于汉字字符识别的工作就完成了许多。

小幽余生不加糖 1650

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

【C++学习笔记】类型转换和跳转语句

在C++语言中,如果两种类型由关联,那么当程序需要其中一种类型的运算对象时,可以用另一种类型的对象或值来替代,即如果如果两种类型可以相互转换(conversion),那么它们就是关联的。

Lawe的博客 735

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

C++ 类型转换(随进度更新)

1.隐式(自动)类型转换 隐式(自动)类型转换是自动执行的,无需显式操作符。 数值类型转换规则: 1.浮点转整数,忽略掉小数部分。 float a = -1.5f; int b = a; // b = -1 2.整数转浮点,小数部分记为0。 int i=1; double b=i;//b=1.0000 3.有符号类型向无符号类型转换,且超出无符号数的表示范围时,结果是初始值对无符号类型表示数值总数取模后的余数。 int a = -1; unsigned int b = a;

excellentcx的博客 294

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

C++高级使用技巧:强制类型转换

在C语言中,如果表达式赋值运算符左右两侧变量或表达式的数据类型不同,或者形参变量与实参变量类型不匹配,或者返回值变量类型与接收值类型不一致时,就需要进行类型转化,C++语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换。隐式类型转化是编译器在自动进行,能转就转,不能转就会发生编译失败;而显式类型转化(强转)是用户自己进行类型转换操作。

qq_36756667的博客 720

C++类型转换

C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况: 1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。   int ival = 3; double dval = 3.14159; ival + dval;//

abcd1f2的专栏 429

c++中的类型转换

首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况: 1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。   int ival = 3; double dval = 3.14159;

陈嘉怡的专栏 768

static_cast, dynamic_cast, const_cast探讨

C++类型转换分为:隐式类型转换和显式类型转换 第1部分.隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。 intival=3;doubledval=3.14159;ival+dval;//ival被提升为double类型 2)一种类...

weixin_30263073的博客 1477

特殊类的设计、C++四种类型转换

特殊类的设计、C++四种类型转换

一怀明月的博客 1389

【More Effective C++ 条款5】对定制的“类型转换函数”保持警觉

1)C++允许内置数据类型之间进行隐式转换,比如char转int,int转double,对于内置数据类型的转换有详细的规则,但不管怎么样,这些都是语言提供的,相对安全,而且我们无法更改对于自定义类的类型,其隐式类型可以通过带单一自变量的构造函数和隐式类型转换操作符来实现2)单一自变量构造函数:指能够以单一自变量成功调用的构造函数,该构造函数可能只有一个参数,也可能有多个参数,并且除了第一...

Y先森0.0 301
上一篇: C++: Virtual关键字的几种用法
下一篇: C++基础(3) - Singleton单例模式
kevin@1024
博客等级 码龄11年 677粉丝 95原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值