您的位置:首页 > 编程语言 > C语言/C++

[C++] C++风格的强制类型转换探讨

2014-01-05 21:37 239 查看
C++风格的强制类型转换:const_caststatic_castdynamic_castreinterpret_cast

使用:xxx_cast<type-id> (expression)

[b]const_cast[/b]

说明:该运算符用来修改类型的const或volatile属性。

class TestA
{
public:
TestA() { }
public:
int m_data;
};

void foo()
{
const TestA ta;
//ta1.m_data = 100;    //编译错误

TestA *pTa = const_cast<TestA*>(&ta);
pTa->m_data = 200;     //OK

TestA &taTmp = const_cast<TestA&>(ta);
taTmp.m_data = 300;    //OK
}

int main( int argc, char * argv[] )
{
foo();
return 0;
}


[b]static_cast[/b]

说明:无条件强制转换,没有在运行时进行类型检查来保证转换的安全性,static_cast也不能去掉类型的const、volitale属性。

场景:

基类和子类之间转换:进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。

用于基本数据类型之间的转换,如把int转换成char,把int转换成enum等。

把空指针转换成目标类型的空指针。

把任何类型的表达式转换成void类型。

void foo()
{
int n = 6;
char c = static_cast<char>(n);          // 基本类型转换
double d = static_cast<double>(n);
float f = static_cast<float>(n);

int *pn = &n;
//double *d = static_cast<double*>(&n)  //无关类型指针转换,编译错误
void *p = static_cast<void*>(pn);       //任意类型转换成void类型
}

int main( int argc, char * argv[] )
{
foo();
return 0;
}


[b]dynamic_cast[/b]

说明:type-id必须是类的指针、类的引用或者void*,运行时会进行类型安全检查(转换失败返回NULL)。

场景:

基类和子类之间转换,上行和下行转换都是安全的。

基类必须要有虚函数。

交叉转换(相同基类的不同子类之间的转换),但结果是NULL。

#include <string.h>
#include <iostream>

using namespace std;

class BaseClass
{
public:
int m_data;
virtual void btest(){}; //基类必须有虚函数
};

class DerivedClass : public BaseClass
{
public:
char m_arr[100];
void dtest(){};
};

void foo()
{
BaseClass* pb = new DerivedClass();
DerivedClass *pd1 = static_cast<DerivedClass *>(pb);   //子类->父类,静态类型转换,正确但不推荐
DerivedClass *pd2 = dynamic_cast<DerivedClass *>(pb);  //子类->父类,动态类型转换,正确

BaseClass* pb2 = new BaseClass();
DerivedClass *pd3 = static_cast<DerivedClass *>(pb2);  //父类->子类,静态类型转换,危险!
//strcpy(pd3->m_arr, "0123456789");                    //访问子类m_arr成员越界,造成运行时错误。

DerivedClass *pd4 = dynamic_cast<DerivedClass *>(pb2); //父类->子类,动态类型转换,安全。结果为NULL。
if (NULL == pd4)
{
cout << "null == pd4" << endl;
}
}

int main( int argc, char * argv[] )
{
foo();
return 0;
}


[b]reinterpret_cast[/b]

说明:仅仅重新解释类型,但没有做字节对齐。

场景:最普通的用途就是在函数指针类型之间进行转换,但是很难保证移植性。

#include<iostream>

using namespace std;

class TestA
{
public:
int m_a;
};

class TestB
{
public:
int m_b;
};

class TestC : public TestA, public TestB
{};

void foo()
{
TestC tc;

cout << "&tc = 0x" << &tc << endl;
cout << "reinterpret_cast<TestB*>(&tc) = 0x" << reinterpret_cast<TestB*>(&tc) << endl;
cout << "static_cast<TestB*>(&tc) = 0x" << static_cast<TestB*>(&tc) << endl;
}

int main( int argc, char * argv[] )
{
foo();
return 0;
}


结果:



static_cast转换之后结果 - reinterpret_cast转换之后的结果 = 4(即该测试类中的字节对齐长度)。

说明:static_cast在进行上行转换是安全的,static_cast计算了父子类指针转换的偏移量,并将之转换到正确的地址,而reinterpret_cast则不会做这层转换。

[b]总结[/b]

const_cast:去const或volatile属性时用到。

static_cast:基本类型转换(不包括指针类型)时用到。

daynamic_cast:基类与子类的指针(或引用)互相转换时用到。

reinterpret_cast:不同类型的指针类型转换(如:函数指针类型之间进行转换),慎用。

[b]参考[/b]

http://baike.baidu.com/view/1745221.htm

http://baike.baidu.com/view/1745207.htm

http://baike.baidu.com/view/1745213.htm

http://baike.baidu.com/view/1263731.htm

http://www.cnblogs.com/goodhacker/archive/2011/07/20/2111996.html

(完)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: