一个VC编译错误引发的对显示类型转换的思考(static_cast、dynamic_cast和const_cast)(五)

2014-11-24 02:21:07 · 作者: · 浏览: 8
Point p1(1, 2);
Point3d p2(1, 2, 3);
f(&p1, &p2);
return 0;
}
在上面的代码段中,将子类对象p2转为父类对象pa是安全的,而将父类对象p1转为子类对象pb也是安全的,因为pb将是一个空指针(即0,因为dynamic_cast失败)。
另外要注意:Base要有虚函数,否则会编译出错;static_cast则没有这个限制。
这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。
dynamic_cast支持交叉转换(cross cast)如下代码所示:
[cpp]
class Base
{
public:
int m_iNum;
virtual void f(){}
};
class Derived1 : public Base
{
};
class Derived2 : public Base
{
};
void foo()
{
derived1 *pd1 = new Drived1;
pd1->m_iNum = 100;
Derived2 *pd2 = static_cast(pd1); //compile error
Derived2 *pd2 = dynamic_cast(pd1); //pd2 is NULL
delete pd1;
}
在函数foo中,使用static_cast进行转换是不被允许的,将在编译时出错;而使用 dynamic_cast的转换则是允许的,结果是空指针。
(3)const_cast
用法:const_cast(expression)
说明:该运算符用来修改类型的const或volatile属性。除了const或volatile修饰之外,type_id和expression的类型是一样的。
使用场景:
a、常量指针被转化成非常量指针,并且仍然指向原来的对象;
b、常量引用被转换成非常量引用,并且仍然指向原来的对象;
c、常量对象被转换成非常量对象。
Voiatile和const类似。
[cpp]
// CastExample.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
using namespace std;
class point
{
private:
int m_x,m_y;
public:
point()
{
m_x = 0;
m_y = 0;
}
point(int x, int y)
{
m_x = x;
m_y = y;
}
point(const point& p)
{
m_x = p.m_x;
m_y = p.m_y;
cout<<"copy constructor is called!"<
}
static point reverse(const point& p)
{
point p1, p2;
p2 = const_cast(p); //将const point类型显示转换为point类型
p1.m_x = p2.getY();
p1.m_y = p2.getX();
return p1;
}
int getX()
{
return m_x;
}
int getY()
{
return m_y;
}
void print()
{
cout<
}
};
int main()
{
point p(1, 2);
point p1(p); //initialize p1 with p
point p2 = point::reverse(p1);
p2.print();
return 0;
}
注意<>和()中的类型一定要一致,都为引用或者都为指针或都为对象!
五、小结
C++的四种强制转型形式每一种适用于特定的目的:
  ·dynamic_cast 主要用于执行“安全的向下转型(safe downcasting)”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型,也是唯一可能有重大运行时代价的强制转型。
·static_cast 可以被用于强制隐型转换(例如,non-const 对象转型为 const 对象,int 转型为 double,等等),它还可以用于很多这样的转换的反向转换(例如,void* 指针转型为有类型指针,基类指针转型为派生类指针),但是它不能将一个 const 对象转型为 non-const 对象(只有 const_cast 能做到),它最接近于C-style的转换。
  ·const_cast 一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型。
  ·reinterpret_cast 是特意用于底层的强制转型,导致实现依赖(implementation-dependent)(就是说,不可移植)的结果,例如,将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。
(2013年11月14日 0:02)