当前位置: 首页 > 科技观察

C++的转换方法和Explicit关键字

时间:2023-03-19 23:02:31 科技观察

C一起使用我们会进行各种类型的强制转换,在C中我们经常可以看到这种转换memset(OTA_FLAG_ADDRESS,(uint8_t*)&OTA_Flag,sizeof(OTA_Flag));而C++的类型转换与C有很大不同,那么C++中的类型转换是如何使用的呢?除了隐式转换和显式转换,C++还熟悉显式转换。显式转换函数有四种:static_cast、dynamic_cast、const_cast、reinterpret_cast,主要用于继承关系类之间的强制转换。接下来,我就给大家说一说。隐式转换C++语言不会直接将两个不同类型的值相加。二十首先尝试根据类型转换规则统一操作数的类型,然后再进行评估。例如int值=3.14+3;该程序可以编译,但编译器可能会警告该操作会丢失精度。这种类型转换是自动进行的,不需要程序员的干预,因此称为隐式转换当发生隐式转换时:编译器会在以下情况下自动转换操作数的类型:在大多数表达式中,整数值小于int类型需要先提升为更大的整数类型,然后进行隐式转换。在条件中,将非布尔值转换为布尔类型。在初始化过程中,将初始值转换为变量的类型;在赋值语句中,右操作数被转换为左操作数的类型。调用函数时也会发生类型转换(实参类型转换)可以使用下面的方法Typeb=(Type)a;当然,C++也支持C风格的强制转换,但是C风格的强制转换可能会带来一些隐患,使得一些问题难以被发现。因此,C++提供了一套可以在不同场合使用的强制转换函数。C++提供了四种强制类型转换的函数,即:static_cast,在命名上理解为静态类型转换。C实现的大部分转换都可以用这个函数来完成。const_cast,字面意思是转到const属性。dynamic_cast,命名理解就是动态类型转换。比如子类和父类之间的多态类型转换。reinterpret_cast,只重新解释类型,不进行二进制转换。static_cast:任何定义良好的类型转换,只要不包含底层const,都可以使用static_cast,举个例子。doubleslop=static_cast(j)/i;//强行转为doubleint*pn=&n;double*dp=static_cast(&pn)//无关类型指针转换,编译错误void*p=&n;double*d=static_cast(&p)//将void*转换为初始指针类型static_castcast只会在编译时检查,没有运行时类型检查来保证转换的安全。同时,static_cast也不能??去除expression的const、volitale或__unaligned属性。const_cast:const_cast<>可以实现const指针类型到普通指针的转换,const_cast操作不能在不同类型之间转换。相反,它只是将其作用的表达式转换为常量。它可以将一个本来就不是const类型的数据转换成const类型,或者去掉const属性。如果对象本身不是常量,则使用强制转换来获得写访问权是合法的。但是,如果对象是常量,则使用const_cast执行写操作会产生未定义的后果。只有const_cast可以改变表达式的常量属性。使用其他形式的命名转换来更改表达式的常量属性将导致编译器错误。同样,const_cast不能用来改变表达式的类型:constchar*cp;char*q=static_cast(cp);//错误:static_cast不能转换const属性static_cast(cp);//正确:字符串字面量值转换为字符串类型const_cast(cp);//错误:const_cast只改变常量属性const_cast(cp);//正确constintp=0;int&rb=const_cast(p);//修正rb=10;dynamic_cast:1.其他三个在编译时完成,dynamic_cast在运行时处理,需要在运行时进行类型检查。2、不能用于内置基本数据类型的强制转换。3.如果dynamic_cast转换成功,则返回类的指针或引用,如果转换失败,则返回NULL。4.如果使用dynamic_cast进行转换,基类中必须有虚函数,否则会编译失败。可以从父类传递给基类,但可能为空。5.类转换时,dynamic_cast和static_cast在类层次间进行向上转换时效果相同。在向下转型时,dynamic_cast具有类型检查的功能,比static_cast更安全。向上转型就是向下转型为子类对象,即将父类指针转换为子类指针。向下转型的成功与否还与要转换的类型有关,即要转换的指针指向的对象的实际类型必须与转换后的对象类型相同,否则转换失败。classBaseClass{public:intNum;virtualvoidfoo(){};//基类必须有虚函数。保留多个功能以使用dynamic_cast};DerivedClass:publicBaseClass{public:char*m_szName[100];voidbar(){};};intmain(intargc,char**argv){BaseClass*pb=newDerivedClass();DerivedClass*pd1=static_cast(pb);//子类->父类,静态类型转换,正确但不推荐DerivedClass*pd2=dynamic_cast(pb);//子类->父类,动态类型转换,正确的BaseClass*pb2=newBaseClass();DerivedClass*pd21=static_cast(pb2);//父类->子类,静态类型转换,危险!越界访问子类m_szName成员DerivedClass*pd22=dynamic_cast(pb2);//父类->子类,动态类型转换,安全。结果是NULLreinterpret_cast:implementpointertointeger,integertopointer.reinterpret_cast被强制类型转换运算符用来处理不相关的类型转换,通常为操作数的位模式提供更底层的重新解释!但它只是重新解释为对象的位模型,并没有转换为二进制!它用于任意指针之间的转换、引用之间的转换、指针和足够大的int类型之间的转换以及从整数到指针的转换。最常见的用途是在函数指针类型之间进行转换。请看一段简单的代码intdoSomething(){return0;};typedefvoid(*FuncPtr)();//FuncPtris是一个函数指针,函数没有参数,返回值类型为voidFuncPtrfuncPtrArray[10];//10FuncPtrs指针假设您希望(出于某些无法解释的原因)在funcPtrArray数组中存储指向以下函数的指针:funcPtrArray[0]=&doSomething;//编译错误!类型不匹配,reinterpret_cast可以让编译器按你的方式处理:funcPtrArrayfuncPtrArray[0]=reinterpret_cast(&doSomething);//不同函数指针类型之间的转换explicitkeyword(displayedtypeconversionoperator)C++提供的关键字explicit,它可以防止不应该通过转换构造函数允许的隐式转换。也就是说,声明为显式的构造函数不能用于隐式转换。explicit关键字只能用于类内的构造函数声明,不能用于类外的函数定义。现在Things类看起来像这样:classThings{public:Things(conststd::string&name="");explicitoperatorint()const{returnval;}//编译器不会自动执行这个类型};让我们看一个更好的例子来比较://通过构造函数的类隐式转换:#includeusingnamespacestd;classA{};classB{public://conversionfromA(constructor):B(constA&x){}//conversionfromA(assignment):B&operator=(constA&x){return*this;}//转换为A(type-castoperator)operatorA(){returnA();}};intmain(){Afoo;Bbar=foo;//调用构造函数实现implicit类型转换bar=foo;//callsassignmentfoo=bar;//callstype-castoperator,相当于foo=A(bar);return0;}看一个使用explicit的例子:#includeusingnamespacestd;classA{};classB{public:explicitB(constA&x){}B&operator=(constA&x){return*this;}operatorA(){returnA();}};voidfn(Bx){}//当我们希望x只能是类型B、我们需要禁止隐式类型转换intmain(){Afoo;Bbar(foo);//必须是显式类型转换,不再允许Bbar=foo;bar=foo;foo=bar;//fn(foo);//不允许隐式类型转换fn(bar);return0;}这是我的c++转换类型方法shared,指的是多人分享的文字。另外,如果大家有更好的想法,欢迎大家分享交流。本文转载自微信公众号“羽林君”,可通过以下二维码关注。转载本文请联系羽林君公众号。