本文主要介绍c中类型转换static_cast、dynamic_cast、const_cast、reinterpret_cast的总结,有需要的朋友可以参考一下。
前言
本文总结了c中的类型转换,有时候我不太关注这些小知识点,但是在实际开发中经常用到。俗话说,不懂自己代码的程序员不是好程序员;如果一个程序员对自己的代码一无所知,只知道傻乎乎地用,总有一天,你会迷失自我。
C #中有两种类型的类型转换:
1.隐式类型转换;
2.显式类型转换。
对于隐式转换,它是标准转换。在很多情况下,它是在不经意间发生的。例如,当添加int类型和float类型时,int类型将隐式转换为float类型,然后执行加法操作。隐式转换不是今天总结的重点,而是显式转换。标准c中有四种类型转换器:static_cast、dynamic_cast、const_cast和reinterpret _ cast;下面将一一总结。
static_cast
static_cast的转换格式:static_cast type-id(表达式)
将expression转换为type-id主要用于非多态类型之间的转换,不提供运行时检查来保证转换的安全性。主要用于以下情况:
1.用于类层次结构中基类和子类之间指针和引用的转换;
当进行向上转换时,即子类的指针或引用转换为父类的表示时,这种转换是安全的;
向下转换时,即把父类的指针或引用转换成子类的表示,这种转换是不安全的,也需要程序员的保证;
2.用于基本数据类型之间的转换,比如将int转换成char,将int转换成enum等。这种转换的安全性需要程序员来保证;
3.将void指针转换为目标类型的指针是极其不安全的;
注意:static_cast不能转换表达式的const、volatile和__unaligned属性。
dynamic_cast
dynamic_cast的转换格式:dynamic_cast type-id(表达式)
将expression转换为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继承自A,B转换为A,因此对于上行转换是安全的,如下所示:
复制代码如下:
#包括iostream
使用命名空间std
A级
{
//.
};
B类:公共A
{
//.
};
int main()
{
B *pB=新B;
a * pA=dynamic _ castA *(pB);//安全并且会成功
}
2.多个继承之间的向上转换
c继承B,B继承A,是多重继承关系;但是,关系很清楚,使用dynamic_cast进行转换时,也很简单:
复制代码如下:
A级
{
//.
};
B类:公共A
{
//.
};
C类:公共B类
{
//.
};
int main()
{
C *pC=新C;
b * pB=dynamic _ castB *(pC);//好的
a * pA=dynamic _ castA *(pC);//好的
}
上面的转换,static_cast和dynamic_cast的效果是一样的。并且这种上行转换也称为隐式转换;比如我们在定义变量的时候经常这样写:B * pB=new C;除了添加了一个dynamic_cast转换器之外,这与上面的相同。
3.转换为void *
您可以将类转换为void *,例如:
复制代码如下:
A级
{
公共:
虚拟void f(){}
//.
};
B类
{
公共:
虚拟void f(){}
//.
};
int main()
{
A *pA=新A;
B *pB=新B;
void * pV=dynamic _ cast void *(pA);//pV指向的对象
pV=dynamic _ cast void *(pB);//pV指向B的一个对象
}
但是虚函数必须包含在A类和b类中,为什么呢?因为类中有虚函数,意味着它希望基类的指针或引用指向派生类的对象,然后转换才有意义;因为运行时类型检查需要运行时类型信息,而这些信息存储在类的虚函数表中,所以只有定义虚函数的类才有虚函数表。
4.如果expression是type-id的基类,那么使用dynamic_cast进行转换时,会在运行时检查expression是否真的指向type-id的对象,如果是,就可以正确转换得到相应的值;否则,返回NULL如果是引用,运行时会抛出异常;例如:
复制代码如下:
B类
{
虚拟void f(){ };
};
D类:公共B类
{
虚拟void f(){ };
};
void main()
{
B* pb=新D;//不清楚但还可以
B* pb2=新B;
d * PD=dynamic _ castD *(Pb);//好的:pb其实指向一个D
d * pd2=dynamic _ castD *(Pb2);//pb2指向a B不是a D,现在pd2为空
}
这是从基类指针到派生类指针的向下转换。
对于一些复杂的继承关系,使用dynamic_cast进行转换存在一些陷阱;例如,有如下结构:
d型可以安全的转换成b型和c型,但是如果d型直接转换成a型呢?
复制代码如下:
A级
{
虚拟void Func()=0;
};
B类:公共A
{
void Func(){ };
};
C类:公共A
{
void Func(){ };
};
D类:公共B、公共C
{
void Func(){}
};
int main()
{
D *pD=新D;
a* pA=dynamic _ castA *(pD);//你会得到一个空的pA
}
如果你做上面的直接转移,你会得到一个空的pA指针;这是因为B和C都继承了A,都实现了虚函数func,导致无法决定A应该转换成哪个。正确的做法是:
复制代码如下:
int main()
{
D *pD=新D;
b * pB=dynamic _ castB *(pD);
a * pA=dynamic _ castA *(pB);
}
也就是我在实现QueryInterface时获取IUnknown的指针时,用的是* PPV=static _ castIX *(this);而不是* PPV=static _ cast unknown *(this);
在多重继承的情况下,从派生类转移到父类的父类时要特别注意。例如,有以下几种情况:
现在,你有一个A类型的指针,它指向实例E。你如何得到一个B类型的指针,它指向实例E?如果直接做翻译,编译器会有差异。不知道是走E-C-B还是E-D-B,这种情况下首先要把A类型的指针向下转换得到E类型的指针,然后指定一个正确的路线向上转换。
以上是关于dynamic_cast转换的一些细节,特别是对于多重继承的情况。在实际项目中,很容易出现问题。
const_cast
const_cast的转换格式:const_cast type-id(表达式)
Const_cast用于移除类型的Const、volatile和__unaligned属性。Const指针转换为非常数指针,仍然指向原始对象;常量引用被转换为非常量引用,而原始对象仍被引用。请看下面的代码示例:
复制代码如下:
/*
**文件名:ConstCastDemo
**作者:杰利扬
**日期:2013年12月27日
**描述:更多信息,请到https://www.jb51.net
*/
#包括iostream
使用命名空间std
CA级
{
公共:
CA():m_iA(10){}
int m _ iA
};
int main()
{
const CA *pA=新CA;
//pA-m _ iA=100;//错误
CA * pB=const _ cast CA *(pA);
p B- m _ iA=100;
//现在pA和pB指向同一个对象
cout pa-m _ iAendl;
cout Pb-m _ iAendl;
const CA a=* pA
//a . m _ iA=200;//错误
CA b=const _ cast CA(a);
p B- m _ iA=200;
//现在a和b引用同一个对象
coutb.m _ iAendl
couta.m _ iAendl
}
注意:不能通过在非指针和非引用变量上使用const_cast操作符来直接删除它的const、volatile和__unaligned属性。
reinterpret_cast
reinterpret_cast的转换格式:reinterpret _ cast type-id(表达式)
允许将任何指针类型转换为其他指针类型;听起来很厉害,但也不靠谱。它主要用于将一种数据类型从一种类型转换为另一种类型。它可以将指针转换成整数,也可以将整数转换成指针。在实际开发中,先将一个指针转换成一个整数,再将整数转换成原始指针,就可以得到原始指针值。特别是,它打开了系统的全局内存空间。当它需要在多个应用程序中使用时,它需要相互共享。当这个内存空间的指针经过时,可以将指针转换成整数值,然后将整数值转换成指针进行相应的操作。
总结
这篇博文总结了C中的类型转换,重点是显式转换。详细描述了C支持的四种显式转换。如果你有什么要补充的,或者我的总结有什么不对的地方,请给我们提意见。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。