C++类型转换运算符(Type Conversion Operators)

C++类型转换运算符(Type Conversion Operators) 

1.static_cast 

将一个值以合逻辑的方式转换。着可以看做是"利用原值重新构造一个临时对象,并在设立初值的时候使用类别转换"。唯有当上述的类型转换有所定义,整个转换才会成功。

所谓的"有所定义",可以是语言内建规则,也可以是程序员自定的转换动作。

eg:

#include <iostream>
using namespace std;
int main()
{
float f = 100.555;
cout
<< static_cast<int>(f)<<endl;
return 0;
}
2.dynamic_cast 

将多态型别(polymorphic type)向下转型(downcast)为其实际静态类型(real static type)

这是唯一在运行期进行检验的转型动作。你可以用它来检验某个多态对象的类型(polymorphic value)

eg: 

#include <iostream>
using namespace std;

class Car
{
public:
virtual void function()
{
}
};
class Cabriolet:public Car
{
public:
virtual void function()
{
cout
<< "Cabriolet::function" << endl;
}
};
class Limousine:public Car
{
public:
virtual void function()
{
cout
<< "Limousine::function" << endl;
}
};
void func(Car* cp)
{
Cabriolet
* p = dynamic_cast<Cabriolet*> (cp);
if(p == NULL)
{
cout
<< "did not refer to an object of type Cabriolet" << endl;
}
else
{
cout
<< "can refer to an object of type Cabriolet" << endl;
}
Limousine
* p2 = dynamic_cast<Limousine*>(cp);
if(p2 == NULL)
{
cout
<< "did not refer to an object of type Limousine" << endl;
}
else
{
cout
<< "can refer to an object of type Limousine" << endl;
}
cout
<< endl;
}
int main()
{
Car car;
Cabriolet cabriolet;
Limousine limousine;

func(
&car);
func(
&cabriolet);
func(
&limousine);

return 0;
}

运行结果为:
did not refer to an
object of type Cabriolet
did not refer to an
object of type Limousine

can refer to an
object of type Cabriolet
did not refer to an
object of type Limousine

did not refer to an
object of type Cabriolet
can refer to an
object of type Limousine

Process returned
0 (0x0) execution time : 0.078 s
Press any key to
continue.
eg:
struct A {
virtual void f() { }
};
struct B : public A { };
struct C { };

void f () {
A a;
B b;

A
* ap = &b;
B
* b1 = dynamic_cast<B*> (&a); // NULL, because 'a' is not a 'B'
B* b2 = dynamic_cast<B*> (ap); // 'b'
C* c = dynamic_cast<C*> (ap); // NULL.

A
& ar = dynamic_cast<A&> (*ap); // Ok.
B& br = dynamic_cast<B&> (*ap); // Ok.
C& cr = dynamic_cast<C&> (*ap); // std::bad_cast
}

在这个例子中,面对实际的静态类别为Cabriolet的物件,f()有特殊的应对行为。当参数是一个reference,而且类别转换失败时,dynamic_cast丢出一个bad_cast异常。

注意,从设计者角度而言,你应该运用多态技术的程序中,避免这种"程序行为取决于具体类型 "的写法。 

3.const_cast 

设定或取出类别的常数性,亦可除volatile饰词。除此之外不允许任何转换。 

eg: 

 

#include <iostream>
using namespace std;
void f(int* p)
{
cout
<< *p << endl;
}
int main(void) {
const int a = 10;
const int* b = &a;
// Function f() expects int*, not const int*
// f(b);
int* c = const_cast<int*>(b);
f(c);
// Lvalue is const
// *b = 20;
// Undefined behavior
// *c = 30;
int a1 = 40;
const int* b1 = &a1;
int* c1 = const_cast<int*>(b1);
// Integer a1, the object referred to by c1, has
// not been declared const
*c1 = 50;
cout
<< *c1 << endl;
return 0;
}

The compiler will not allow the function call f(b). Function f() expects a pointer to an int, not a const int. The statement 

int* c = const_cast<int>(b) returns a pointer c that refers to a without the const qualification of a. This process of using

 const_cast to remove the const qualification of an object is called casting away constness. Consequently the compiler will 

allow the function call f(c). 

The compiler would not allow the assignment *b = 20 because b points to an object of type const int. The compiler will allow 

the *c = 30, but the behavior of this statement is undefined. If you cast away the constness of an object that has been

 explicitly declared as const, and attempt to modify it, the results are undefined. 

However, if you cast away the constness of an object that has not been explicitly declared as const, you can modify 

it safely. In the above example, the object referred to by b1 has not been declared const, but you cannot modify

 this object through b1. You may cast away the constness of b1 and modify the value to which it refers. 

4.reinterpret_cast 

此运算符的行为由编译器定义。可能重新解释bits意义,但也不一定如此。使用此一转型动作通常带来不可移植性。 

The reinterpret_cast operator changes one data type into another. It should be used to cast between incompatible pointer types.  

  这些操作符取代了以往小圆括号所代表的旧式转型,能够清楚阐明转型的目的。小圆括号转型可替换dynamic_cast之外的其他三种转型,也因此你运用它时,你无法明确显示用它的确切理由。

这些新式转型操作符给了编译器更多的信息,让编译器清楚知道转型的理由,并在转型失败时释出一份错误报告。

参考资料: 

C++标准程序库》侯捷 孟岩译 

http://www.cppreference.com/wiki/keywords/dynamic_cast 

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/keyword_const_cast.htm 

http://www.cppreference.com/wiki/keywords/reinterpret_cast 

 

本文完

转载请表明出处,谢谢

2010-08-19

posted @ 2010-08-19 09:21  独酌逸醉  阅读(2566)  评论(0编辑  收藏  举报