转自:http://tianyufeixiang.blog.163.com/blog/static/79370408201071332056265/
本人没有验证!
在C中几乎可以将任何类型强制转化成另外一种类型。这点是C的特点,也是C中容易出错的地方,让程序员对转化结果负责。C++除了兼容C强制转换操作符号外还增加了4个类型转化操作符号分别是static_cast、const_cast、dynamic_cast、reinterpret_cast。
static_cast 使用在大多数数据类型转换地方,比如将Unsigned int转化int,一般用于数据类型转化。
const_cast 用于将const类型转化为非const类型。这点属于容易出错的地方,在C中也可以使用强制转换操作符完成这个过程。但const_cast是关键字,在任何编辑器中都很容易找到使用的地方。一旦遇到因为const转换到非const的问题,立即就能够找到转化的地方进行检查调试。而使用C风格的转换符号则比较加难找。一没语法高亮,二没固定字符串可以搜索,三C风格的转换操作符样子都一样不容易区分。容易在出问题的时候快速找到这一个理由足够说服使用 const_cast
dynamic_cast 用于把基类指针或引用转换成派生类的指针或引用。如果在需要用到dynamic_cast的地方使用C风格的转换操作符那就是大错特错了。看以下代码
class A
{
public:
virtual ~A() {}
};
class B
{
public:
virtual ~B() {}
};
class C:public A,public B
{
};
class D:public B
{
};
int main( int argc, char* argv[] )
{
C* p = new C;
A* pA = p;
B* pB = p;
printf( "%p\t%p\t%p\n" , p , pA , pB );
printf( "%p\t%p\t%p\n" , p , ( C* )pA , ( C* )pB );
printf( "%p\t%p\t%p\n" , ( D* )p , ( D* )pA , ( D* )pB );//注意这一行
printf( "%p\t%p\t%p\n" , dynamic_cast<D*>( p ) ,dynamic_cast<D*>( pA ) , dynamic_cast<D*>( pB ) );
delete p;
return 0;
}
在我机器上输出如下
00394FD8 00394FD8 00394FDC
00394FD8 00394FD8 00394FD8
00394FD8 00394FD8 00394FDC
00000000 00000000 00000000
在将指针p转化成D*类型的时候使用了2中方法,结果却完全不同。很明显p不是D类型的,转化成D类型应该失败,而C风格却成功了。可以想像这样的代码会带来怎样的隐患
在这里dynamic_cast给出了正确的结果,正是我们所期望的结果。
reinterpret_cast C类型转化的替代品,功能和C的强制转换操作符号一模一样。即使功能相同,但也应该优先使用reinterpret_cast。因为在编辑器中reinterpret_cast关键字非常醒目,能够时时提醒这是一个需要程序员承担后果的转换。
在C中有一个为了兼容旧代码的规定,那就是char* p=”aa”的合法。在这里将一个const char*类型转化成了char*,本来不合法的事情在这里变成了合法。于是很容易就有人写出类似的代码
int main() { char* p="aaa" ; strcpy( p , "bb" ); //原型声明:extern char *strcpy(char *dest,char *src); //把src所指由NULL结束的字符串复制到dest所指的数组中。 //src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。 return 0; } 绝大多数编译器编译这个代码都不会有警告,但运行的时候基本上都会给一个系统异常正确的写法应该是:
int main()
{
const char* p="aaa" ;
strcpy( p , "bb" );//编译错误
return 0;
}