C++显式转换

C++中,显式转换也称为强制类型转换(cast)。包括下列名字命名的强制类型转换操作符:static_cast、dynamic_cast、const_cast和reinterpret_cast。

 

用法

cast-name<type>(expression)

cast-name就是强制类型转换操作符,type是转换的目标类型,expression则是被强制转换的表达式。

 

const_cast

作用:修改类型的const或volatile属性。除了const 或volatile修饰之外, type和expression的类型是一样的

一、常量指针被转化成非常量的指针,并且仍然指向原来的对象;
二、常量引用被转换成非常量的引用,并且仍然指向原来的对象;
三、const_cast一般用于修改底指针。如const char *p形式。
我们知道const类型的对象不能对其修改其数据成员,会出现编译错误,可通过const_cast处理后进行修改。
 

reinterpret_cast

作用:A  reinterpret_cast operator handles conversions between unrelated types(无关类型).type必须是一个指针、引用、算术类型、函数指针或者成员指针。慎重使用这个强制转换类型符
The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument. You cannot cast away a const or volatile qualification. You can explicitly perform the following conversions:
(1)A pointer to any integral type large enough to hold it
(2)A value of integral or enumeration type to a pointer
(3)A pointer to a function to a pointer to a function of a different type
(4)A pointer to an object to a pointer to an object of a different typeA pointer to a member to a pointer to a member of a different class or type, if the types of the members are both function types or object types
  

reinterpret_cast的一个用途

// expre_reinterpret_cast_Operator.cpp
// compile with: /EHsc
#include <iostream>

// Returns a hash code based on an address
unsigned short Hash( void *p ) {
unsigned int val = reinterpret_cast<unsigned int>( p );
return ( unsigned short )( val ^ (val >> 16));
}

using namespace std;
int main() {
int a[20];
for ( int i = 0; i < 20; i++ )
cout << Hash( a + i ) << endl;
} 

reinterpret_cast与static_cast的区别

//多重继承
class A {
    public:
    int m_a;
};
 
class B {
    public:
    int m_b;
};
 
class C : public A, public B {};
C c;
printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));

 前两个的输出值是相同的,最后一个则会在原基础上偏移4个字节,这是因为static_cast计算了父子类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处),而reinterpret_cast却不会做这一层转换。

 

static_cast

作用:该运算符把expression转换为type类型,但没有运行时类型检查来保证转换的安全性
编译器隐式执行的任何类型转换都可以由static_cast显式完成。比如
double d=97.0
int i=static_cast<int>(d);
//等价于
double d=97.0
int i=d;

仅当类型之间可隐式转换时(除类层次间的下行转换之外),static_cast的转换才合法的,否则出错。

①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性。
 

例子

class base{};
class child:public base{};
base* b;
child *c;
c=static_cast<child*>(b);//下行转换,正确(但是没有动态类型检查,所以是不安全的)
c=b;

注意:C++基本类型指针之间不含有隐式转换(void*除外)需要显式转换,故比如char*不能隐式转换为int*,所以通过static_cast将char*转换为int*是不合法的,出现编译错误。

 

dynamic_cast

作用:将一个基类对象指针(或引用)cast到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理
其中type必须是类的指针、类的引用或者void*,而且type如果是一个类类型指针,expression也是一个指针;如果为类引用,expression也是引用。
 
dynamic_cast运算符可以在执行期决定真正的类型。
 
classB
{
public:
int m_iNum;
virtual void foo();
};
 
classD:publicB
{
public:
char* m_szName[100];
};
 
void func(B* pb)//看看传进来的是基类的指针或者引用还是派生类的指针或者引用
{
D* pd1=static_cast<D*>(pb);
D* pd2=dynamic_cast<D*>(pb);
}
(1)如果 downcast 是安全的(也就说,如果基类指针或者引用确实指向一个派生类对象)这个运算符会传回适当转型过的指针。如果 pb 指向一个 D 类型的对象,pd1 和 pd2 是一样的,并且对这两个指针执行 D 类型的任何操作都是安全的。此时static_cast和dynamic_cast效果一样
(2)如果 downcast 不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个派生类对象)。如果 pb 指向的是一个 B 类型的对象,那么 pd1 将是一个指向该对象的指针,对它进行 D 类型的操作将是不安全的(如访问 m_szName),而 pd2 将是一个空指针。此时dynamic_cast具有类型检查的功能,比static_cast更安全。
 
注意:这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。
 
 
参考:
https://www.ibm.com/support/knowledgecenter/zh/SSLTBW_2.3.0/com.ibm.zos.v2r3.cbclx01/keyword_reinterpret_cast.htm
https://baike.baidu.com/item/reinterpret_cast/9303204?fr=aladdin

转载于:https://www.cnblogs.com/wumianjiao/p/7638980.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值