C++ 类型转换

类型转换

    • 隐式类型转换
    • C语言风格的强制类型转换
      • 对于char short int 类型之间的转换,是通过改变指针类型来实现,
      • 对于浮点类型float、double
      • 对类进行强制类型转换
      • 类 向上转型 向下转型
    • 静态类型转换static_cast
  • 动态强制转换 dynamic_cast

提要:
将派生类对象转换为基类对象(向上转型)
将基类对象转换为派生类对象(向下转型)

补充说明,
这里的对象可以是引用或者指针,一般情况下,向上转型是一种安全行为。
向下转型时,
如果对象定义时是基类,却要转型为派生类,就不被允许
允许的情况是,
比如我定义了一个派生类T的对象,把它转型为基类B的对象。
这时候把这个基类B的对象转型成派生类T的对象就是可以的。

隐式类型转换

常见于算数运算,比如int+float,int会先隐式转换为float再进行加法;

数字转char字符的技巧:
char a = 5
将一位数字转为char类型,上式结果并不是字符’5’
因为按照ascll编码表,‘5’对应的位置是53,
想要得到’5’,
可以再加上字符’0’
char a = ‘0’ +5

对于类来说:
隐式类型转换 允许 向上转型
不允许 向下转型

因为向下转型风险不可控、比如越界访问;

C语言风格的强制类型转换

语法就是,在被转换的变量前写上,要转向的数据类型,用小括号括起来。

浅显的理解(x86下):

对于char short int 类型之间的转换,是通过改变指针类型来实现,

举个例子:

unsigned int a{ 0x00123010 };
unsigned char q1{ (unsigned char)a };
unsigned short w1{ (unsigned short)a };
std::cout <<std::hex<<"q1=" << (int)q1 << std::endl 
std::cout <<"w1=" << w1 << std::endl;

输出 q1=10 w1=3010

由此可见,把4字节的int类型转换为 1字节的char、2字节的short类型时,
会出现内存切片的情况;

从汇编的视角来看,其实只是在传递值的时候,更改了指针的类型来实现了强制转换;

	unsigned int a{ 0x00123010 };
00A37656  mov         dword ptr [a],123010h  
	unsigned char q1{ (unsigned char)a };
00A3765D  mov         al,byte ptr [a]  
00A37660  mov         byte ptr [q1],al  
	unsigned short w1{ (unsigned short)a };
00A37663  mov         ax,word ptr [a]  
00A37667  mov         word ptr [w1],ax  

对于浮点类型float、double

x86有专们用来进行类型转换的汇编指令
cvtsi2sscvtsi2sd
分别对应32位单精度float 和 64位双精度double

对类进行强制类型转换

根据类继承时的规则,基类的成员变量会先放到内存中,
举个例子,写一个只有int类型的成员变量的类,
然后将类对象 强制转换为int*类型;
就可以通过指针偏移来访问每一个成员变量

class T
{
public:
	int a{ 100 }, b{ 101 }, c{ 102 };
};

class T1 :public T
{
public:
	int d{ 103 };
};

int main()
{
	T1 t1;
	int* ptr = (int*)&t1;

	std::cout << ptr[0] << std::endl;
	std::cout << ptr[1] << std::endl;
	std::cout << ptr[2] << std::endl;
	std::cout << ptr[3] << std::endl;
}

输出: 100 101 102 103

类 向上转型 向下转型

//只看变量不看函数的情况

向上转型:将派生类对象 转型为基类

向上转型时,比如基类中有成员变量共占12字节,派生类的成员变量占4字节;由于通过基类指针只能访问基类的成员变量,那么就不会出现 访问超过目标对象的内存范围 的情况;

向下转型时:将基类对象 转型为派生类

向下转型时,通过派生类指针要访问属于派生类的成员变量,就属于非法访问了;因为目标对象是基类,根本就没有创建派生的成员变量,这时候访问,得到的就是一个未知的数;

如上述的例子:

T t;
T1* t1 = (T1*) & t;
std::cout << t1->d;

我的运行结果是:-858993460 ,并不是103

所以向下类型转换,是有风险的;

静态类型转换static_cast

static类型转换在编译时,会检查转换合不合法,不合法就报错;
比如:
我想把类对象的引用 转换成int*类型,用强制类型转换可以,用static类型转换就不行;
在这里插入图片描述

动态强制转换 dynamic_cast

用dynamic_cast可以在对象多态中安全的进行类型转换

dynamic_cast只能用于支持方法多态类型的指针,如果转换成功,返回指针,转换失败,返回nullptr

一般在两种情况中要使用dynamic_cast
1》向下转换downcast
2》跨类转换crosscast

注意点:
1》不要转换this指针
2》当dynamic_cast用于转换引用时,转换失败会抛出异常,所以也不推荐转换引用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值