C++类型转换

        c语言支持相近类型的隐式类型转换和不相近类型的强制类型转换。

int main()
{
	int i = 1;
	double d = 8.88;
	i = d;//相近类型的隐式类型转化
	cout << i << endl;
	int* p = nullptr;
	p = (int*)i;//不相近类型的强制类型转换
	cout << p << endl;
	return 0;
}

        c++兼容c语言的隐式转换和强制转换,同时也做了一些规范。c++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:static_cast、reinterpret_cast、const_cast、dynamic_cast。

        static_cast和reinterpret_cast的用法较为简单,分别对应C语言的隐式类型转换和大部分的强制类型转换(用于不相近类型之间,如int和指针),

int main()
{
	int i = 1;
	double d = 8.88;
	d = static_cast<double>(i);//相近类型
	int* p = nullptr;
	p = reinterpret_cast<int*>(i);//不相近类型
	return 0;
}

        const_cast可以用于去除变量的const属性,用法如下。通过类型转换可以解引用pi对所指向空间做修改。代码的运行结果如下。为什么同一块空间的值不一样?这是因为一开始ci是const类型变量,由于编译器认为ci的值不会被修改,因此会将ci的值预先加载到一块特定的寄存器中,后续每一访问ci时,不是通过访问虚拟地址空间,而是直接从cpu中的寄存器直接取值,后续ci的存储的值被修改为了20,但打印ci时,还是从寄存器中取因此会打印出10。本质是由编译器对const对象存取优化机制导致。想要禁止编译器做这个优化,就在const前面把volatile加上。

int main()
{
	const int ci = 10;
	int* pi = const_cast<int*>(&ci);
	*pi = 20;
	cout << *pi << endl;
	cout << ci << endl;
}

        假设类A和B具有继承关系,基类A的指针可以接受子类B的地址,当运行func函数时,如果传入的是B的地址则没事,但如果传入的是A的地址,则程序会崩溃,因为A内没有_b,这是一个越界访问的问题。在func这样的函数内,如何辨别pa指向的是基类对象的地址还是子类对象的地址呢?这时需要用到dynamic_cast。用法如下。如果pa指向的是子类对象,则转换成功,如果pa指向的是父类对象则转换失败返回nullptr。注意,dynamic_cast的应用只能针对继承中的多态类型(父类必须包含虚函数),dynamic_cast之所以能够识别父类的指针是指向父类对象还是子类对象,是通过对象的虚表的上方存储的标识信息来确定的。

class A
{
public:
    virtual void f()
    {}
	int _a;
};

class B :public A
{
public:
	int _b;
};

void func(A* pa)
{
	B* pb = (B*)pa;
	pb->_a = 1;
	pb->_b = 2;
}
void func(A* pa)
{
	B* pb = dynamic_cast<B*>(pa);
	if (pb)
	{
		pb->_a = 1;
		pb->_b = 2;
	}
}

         在类的构造函数前加explicit关键字可以防止构造时发生隐式类型转换。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值