现在的位置: 首页 > 综合 > 正文

C++四种强制类型转换运算符

2017年11月11日 ⁄ 综合 ⁄ 共 3176字 ⁄ 字号 评论关闭

kezunhai@gmail.com

http://blog.csdn.net/kezunhai

        在编写C++程序时,会遇到强制类型转换,习惯性地我们会使用C-Style形式的强制类型转换,如 Type a = (Type)b,对于基本数据类型,系统也可以自动进行类型转换,如:

int a = 10;
double b = 12.0;
int c = b;
int d = b;

今天来看看标准C++中的四个强制类型转换符:static_castdynamic_castreinterpret_cast、和const_cast

     
 1)static_cast

 
    用法:static_cast <
type-id > ( expression )

 
     说明:该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。

 
    
static_cast将一个值以符合逻辑的方式转换,该操作符用于非多态类型的转换,任何标准转换都可以使用他,即static_cast可以把int转换为double,但不能把两个不相关的类对象进行转换,比如类A不能转换为一个不相关的类B类型。static_cast直线的是非多态转换,本质上是传统c语言强制转换的替代品。如:

	float fx = 12.3;
	int ix = static_cast<int>(fx);
	string str = static_cast<string>("Hello");
	cout<<ix<<" , "<<str.c_str()<<endl;

 
     
它主要有如下几种用法:

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

      (2)用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
      (3)把void指针转换成目标类型的指针(不安全!!)
      (4)把任何类型的表达式转换成void类型。
      注意:static_cast不能转换掉expression的const、volitale、或者__unaligned属性。

 
   
2)dynamic_cast

 
    用法:dynamic_cast <
type-id > ( expression )
 

 
    说明:该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。

 
   
dynamic_cast是唯一一个在运行时进行类型检测的转换,可以使用它来检验多个动态对象,该转换一般用于含有虚函数的基类和派生类直接,如:

class BaseClass
{
public:
	BaseClass();
	virtual void printData(string str);
	virtual void warmInfo(string str);
};

class DrivedClass:public BaseClass
{
	public:
		void scanData();
};

BaseClass* pB;
DrivedClass* pD, mD;
pB = &mD;
pD = dynamic_cast<DrivedClass*>(pB);

         在上面的例子中,最后一条语句表示把指向派生类DrivedClass的基类指针pB转换为派生类DrivedClass的指针,然后将这个指针赋给派生类DrivedClass的指针pD。有人可能会觉得这样做没有意义,既然指针pD要指向派生类为什么不pD
= &mD;这样做更直接呢?

 
       有些时候我们需要强制转换,比如如果指向派生类的基类指针pB想访问派生类pD中的除虚函数之外的成员时,就需要把该指针转换为指向派生类D的指针,以达到访问派生类DrivedClass中特有的成员的目的,比如派生类D中含有特有的成员函数scanData(),这时可以这样来访问该成员dynamic_cast<DrivedClass
*>(pb)->scanData();因为dynamic_cast转换后的结果是一个指向派生类的指针,所以可以这样访问派生类中特有的成员。但是该语句不影响原来的指针的类型,即基类指针pB仍然是指向基类B的。如果单独使用该指针仍然不能访问派生类中特有的成员。

 
     
dynamic_cast的注意事项
        dynamic_cast转换符只能用于指针或者引用。dynamic_cast转换符只能用于含有虚函数的类。dynamic_cast转换操作符在执行类型转换时首先将检查能否成功转换,如果能成功转换则转换之,如果转换失败,如果是指针则反回一个0值,如果是转换的是引用,则抛出一个bad_cast异常,所以在使用dynamic_cast转换之间应使用if语句对其转换成功与否进行测试,比如:

pD = dynamic_cast<DrivedClass*>(pB);
if ( pD)
{
	pD->scanData();
}
else
{
	pD->warmInfo("Error");
}

 
   3)reinterpret_cast

 
     用法:
reinpreter_cast<type-id>
(expression)

 
    说明:type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值),使用该操作符的危险性较高,一般不应使用该操作符。

 
    reinterpret_cast,使用这个操作符的类型转换,其的转换结果几乎都是执行期定义(implementation-defined)。因此,使用reinterpret_casts的代码很难移植。     

 
    
4)const_cast

 
     用法:const_cast<type_id> (expression)

 
     说明:该运算符用来修改类型的const或volatile属性,const_cast最常用的用途就是删除const属性,如果某个变量在大多数时候是常量,而在某个时候又是需要修改的,这时就可以使用const_cast操作符了。除了const
或volatile修饰之外, type_id和expression的类型是一样的。

 
    常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

class TestClass
{
public:
	int m_num;
};

void function(void)
{
	const TestClass test;
	test.m_num = 100; // compile error

	TestClass test2 = const_cast<TestClass>(test);
	test2.m_num = 200; // OK
}

 
    上面的代码编译时会报错,因为test是一个常量对象,不能对它进行改变;使用const_cast把它转换成一个常量对象,就可以对它的数据成员任意改变。

 
    注意:testtest2是两个不同的对象。
参考文章:

1、C++四种强制类型转换运算符

2、static_cast,
dynamic_cast, const_cast探讨

作者:kezunhai出处:http://blog.csdn.net/kezunhai欢迎转载或分享,但请务必声明文章出处。

抱歉!评论已关闭.