[C++特殊操作符] 类型转换static_cast/const_cast/reinterpret_cast/dynamic_cast

使用说明

这些类型转换符号是C++中引入的,而C语言中是通过(NewType)方式进行类型转换的;
此外,对于这些转换的底层逻辑实现没有做深入探究,以后有机会再加。

  • const_cast主要用于去除指针和引用中的const属性(注意不是类型之间转换,而是同一类型的const与非const之间转换)
  • dynamic_cast 耗时,尽量不要用,可以通过设计来避免;并且虚函数不需要
  • static_cast用于一般类型转换较多,而且作为const_cast反向操作
  • reinterpret_cast 只改变对这它的类型解释,不改变底层二进制值,所以你翻译成啥就解释成啥 如果解释和实际存放的值不一致,就会导致读出的值错误–需要小心。

static_cast

  • 和C语言中(newtype)强转是对应的,常用于基本类型之间的转换
  • 注意他和reinterpret_cast的区别,这个是会改底层实际二进制表示的
  • 可以将非const转为const, 也就是可以作为const_cast的反操作(反过来操作只能用const_cast)
  • 也可以将父类指针转为子类指针,注意dynmaic_cast中说的情况–对于非虚函数的情况可能需要dynmaic_cast而不是static_cast
  • static_cast<> 可能在运行时存在一些运行负担,这主要依赖于你转的类型。如果你转的类型是void* 或者非多态对象的层次结构,那么就没有运行时成本;如果你转换一个多态对象(比如子类转父类)可能会有存在偏移更改的消耗,因为vtable需要运行时确定。

const_cast1

  • 用于去除常量中的const属性,但是作用的对象必须是指针,引用;
// 比如, tensorRT API中传入的inputs都是const指针,但是在使用的时候需要非const,则需要在使用前,去掉const
// 注意const_cast不能从const void* 直接转float*,因为它本身只是用于去const的,而不是不同类型之间转换的。
float* input_1 = const_cast<float*>(reinterpret_cast<const float*>(inputs[0]));
// 或者写成
float* input_1 = reinterpret_cast<float*>(const_cast<void*>(inputs[0]));

reinterpret_cast

  • 其实可以直观的理解,也就是转换的只是特性解释,不改变底层二进制值。
  • 根据上一条的理解,我们可以用reinterpret_cast将指针转化为数值;因为我们只是把这个指针的解释改变为size_t数据类型的解释,这样底层表示地址信息的二进制不动,则地址会被翻译成地址数值;这样就能看地址空间范围了。
  • 这也解释了我们经常把无类型的指针void*转换为实际类型指针,也是底层二进制值不动,只是把变量的解释特性改变了,就可以按照指定类型去读从而翻译成真实的数据。
  • reinterpret_cast 是一个纯编译器转换,所以在执行的时候是没有代价消耗的。
float* ptr = new float[2];
ptr[0] = 1;
ptr[1] = 2;
const size_t address_value = reinterpret_cast<size_t>(ptr); // 这样能看ptr本身地址的值
void* n = reinterpret_cast<void*>(ptr);
float* ptr_b = reinterpret_cast<float*>(n); // 这样是可以的,因为保持了对底层二进制的统一类型解释。
// 下面语句错误
int* a = reinterpret_cast<int*>(ptr);
std::cout<<a[0] <<std::endl; // 那么a[0]本来二进制是表示float值的,而上一个语句将其解释为int类型的二进制;则翻译出来实际打印的a[0]的值就不是1了。
  • 转数组指针: reinterpret_cast<Type (&)[num]> test 将test指针转为数组指针。

dynmaic_cast

  • 用来处理一种“安全的向下转换”,当父类指针指向它new出来的多个子类对象时,需要dynamic_cast进行安全转换
  • dynamic_cast的执行速度比较耗时,在多重继承中最好不用,可以通过设计模式来代替类型转换。
  • 用dynamic_cast向下转换的时候,如果转换失败,则返回NULL指针
  • dynamic_cast是针对非虚函数的执行情况使用的,对于虚函数则不需要这种类型转换
#include <iostream>
#include <vector>

class Father{
 public:
  virtual void Function() {std::cout <<"Father"<< std::endl;}
};

class ChildrenA : public Father {
 public:
  virtual void Function() {} 
  void FunctionA() {std::cout <<"A"<< std::endl; }
};

class ChildrenB : public Father {
 public:
  virtual void Function() {}
  void FunctionB() { std::cout <<"B"<< std::endl; }
};

int main() {
 Father *test = new Father;
 Father *testA = new ChildrenA;
 Father *testB = new ChildrenB;
 std::vector<Father*> test_list = {test, testA, testB};
 for (auto it = test_list.begin(); it != test_list.end(); ++it) {
 // 注意,当it不能转换为ChildrenA时,则返回NULL,则这个if条件为false不执行
	if (ChildrenA* a = dynamic_cast<ChildrenA*>(*it)) {
		a->FunctionA();
	} else if (ChildrenB* b = dynamic_cast<ChildrenB*>(*it)) {
		b->FunctionB();
  } else {
		(*it)->Function();
  }
 }
 return 0;
}

reference


  1. (https://blog.csdn.net/bajianxiaofendui/article/details/86616256) ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值