static_cast、dynamic_cast、const_cast和reinterpret_cast总结

发布时间:2026/7/28 14:09:00
static_cast、dynamic_cast、const_cast和reinterpret_cast总结 前言这篇文章总结的是C中的类型转换这些小的知识点有的时候自己不是很注意但是在实际开发中确实经常使用的。俗话说的好不懂自己写的代码的程序员不是好的程序员如果一个程序员对于自己写的代码都不懂只是知道一昧的的去使用终有一天你会迷失你自己的。C中的类型转换分为两种隐式类型转换显式类型转换。而对于隐式变换就是标准的转换在很多时候不经意间就发生了比如int类型和float类型相加时int类型就会被隐式的转换位float类型然后再进行相加运算。而关于隐式转换不是今天总结的重点重点是显式转换。在标准C中有四个类型转换符static_cast、dynamic_cast、const_cast和reinterpret_cast下面将对它们一一的进行总结。static_caststatic_cast的转换格式static_cast (expression)将expression转换为type-id类型主要用于非多态类型之间的转换不提供运行时的检查来确保转换的安全性。主要在以下几种场合中使用用于类层次结构中基类和子类之间指针和引用的转换当进行上行转换也就是把子类的指针或引用转换成父类表示这种转换是安全的当进行下行转换也就是把父类的指针或引用转换成子类表示这种转换是不安全的也需要程序员来保证用于基本数据类型之间的转换如把int转换成char把int转换成enum等等这种转换的安全性需要程序员来保证把void指针转换成目标类型的指针是及其不安全的注static_cast不能转换掉expression的const、volatile和__unaligned属性。dynamic_castdynamic_cast的转换格式dynamic_cast (expression)将expression转换为type-id类型type-id必须是类的指针、类的引用或者是void *如果type-id是指针类型那么expression也必须是一个指针如果type-id是一个引用那么expression也必须是一个引用。dynamic_cast主要用于类层次间的上行转换和下行转换还可以用于类之间的交叉转换。在类层次间进行上行转换时dynamic_cast和static_cast的效果是一样的在进行下行转换时dynamic_cast具有类型检查的功能比static_cast更安全。在多态类型之间的转换主要使用dynamic_cast因为类型提供了运行时信息。下面我将分别在以下的几种场合下进行dynamic_cast的使用总结1.最简单的上行转换比如B继承自AB转换为A进行上行转换时是安全的如下#includeusing namespace std;class A{// …};class B : public A{// …};int main(){B *pB new B;A *pA dynamic_castA *(pB); // Safe and will succeed}2.多重继承之间的上行转换C继承自BB继承自A这种多重继承的关系但是关系很明确使用dynamic_cast进行转换时也是很简单的class A{// …};class B : public A{// …};class C : public B{// …};int main(){C *pC new C;B *pB dynamic_castB *(pC); // OKA *pA dynamic_castA *(pC); // OK}而上述的转换static_cast和dynamic_cast具有同样的效果。而这种上行转换也被称为隐式转换比如我们在定义变量时经常这么写B *pB new C;这和上面是一个道理的只是多加了一个dynamic_cast转换符而已。3.转换成void *可以将类转换成void *例如class A{public:virtual void f(){}// …};class B{public:virtual void f(){}// …};int main(){A *pA new A;B *pB new B;void *pV dynamic_castvoid *(pA); // pV points to an object of ApV dynamic_castvoid *(pB); // pV points to an object of B}但是在类A和类B中必须包含虚函数为什么呢因为类中存在虚函数就说明它有想让基类指针或引用指向派生类对象的情况此时转换才有意义由于运行时类型检查需要运行时类型信息而这个信息存储在类的虚函数表中只有定义了虚函数的类才有虚函数表。4.如果expression是type-id的基类使用dynamic_cast进行转换时在运行时就会检查expression是否真正的指向一个type-id类型的对象如果是则能进行正确的转换获得对应的值否则返回NULL如果是引用则在运行时就会抛出异常例如class B{virtual void f(){};};class D : public B{virtual void f(){};};void main(){B* pb new D; // unclear but okB* pb2 new B;D* pd dynamic_castD*(pb); // ok: pb actually points to a DD* pd2 dynamic_castD*(pb2); // pb2 points to a B not a D, now pd2 is NULL}这个就是下行转换从基类指针转换到派生类指针。对于一些复杂的继承关系来说使用dynamic_cast进行转换是存在一些陷阱的比如有如下的一个结构果冻想 | 一个原创技术分享网站D类型可以安全的转换成B和C类型但是D类型要是直接转换成A类型呢class A{virtual void Func() 0;};class B : public A{void Func(){};};class C : public A{void Func(){};};class D : public B, public C{void Func(){}};int main(){D *pD new D;A *pA dynamic_castA *(pD); // You will get a pA which is NULL}如果进行上面的直接转你将会得到一个NULL的pA指针这是因为B和C都继承了A并且都实现了虚函数Func导致在进行转换时无法进行抉择应该向哪个A进行转换。正确的做法是int main(){D *pD new D;B *pB dynamic_castB *(pD);A *pA dynamic_castA(pB);}这就是我在实现QueryInterface时得到IUnknown的指针时使用的是ppv static_castIX(this);而不是ppv static_castIUnknown *(this);对于多重继承的情况从派生类往父类的父类进行转时需要特别注意比如有下面这种情况果冻想 | 一个原创文章分享网站现在你拥有一个A类型的指针它指向E实例如何获得B类型的指针指向E实例呢如果直接进行转的话就会出现编译器出现分歧不知道是走E-C-B还是走E-D-B。对于这种情况我们就必须先将A类型的指针进行下行转换获得E类型的指针然后在指定一条正确的路线进行上行转换。上面就是对于dynamic_cast转换的一些细节知识点特别是对于多重继承的情况在实际项目中很容易出现问题。const_castconst_cast的转换格式const_cast (expression)const_cast用来将类型的const、volatile和__unaligned属性移除。常量指针被转换成非常量指针并且仍然指向原来的对象常量引用被转换成非常量引用并且仍然引用原来的对象。看以下的代码例子/*** FileName : ConstCastDemo** Author : Jelly Young** Date : 2013/12/27** Description : More information, please go to http://www.jellythink.com*/#includeusing namespace std;class CA{public:CA():m_iA(10){}int m_iA;};int main(){const CA *pA new CA;// pA-m_iA 100; // ErrorCA *pB const_castCA *(pA);pB-m_iA 100;// Now the pA and the pB points to the same objectcoutm_iAendl;coutm_iAendl;const CA a *pA;// a.m_iA 200; // ErrorCA b const_castCA (a);b.m_iA 200;// Now the a and the b reference to the same objectcoutb.m_iAendl;couta.m_iAendl;}注你不能直接对非指针和非引用的变量使用const_cast操作符去直接移除它的const、volatile和__unaligned属性。reinterpret_castreinterpret_cast的转换格式reinterpret_cast (expression)允许将任何指针类型转换为其它的指针类型听起来很强大但是也很不靠谱。它主要用于将一种数据类型从一种类型转换为另一种类型。它可以将一个指针转换成一个整数也可以将一个整数转换成一个指针在实际开发中先把一个指针转换成一个整数在把该整数转换成原类型的指针还可以得到原来的指针值特别是开辟了系统全局的内存空间需要在多个应用程序之间使用时需要彼此共享传递这个内存空间的指针时就可以将指针转换成整数值得到以后再将整数值转换成指针进行对应的操作。