从c++父类与子类指针相互转换看c++强制类型转换

c++与c的类型转换

      • c与c++类型转换的比较
      • c++强制类型转换
        • static_cast与dynamic_cast
        • reinpreter_cast使用
        • const_cast用法
      • 总结

c与c++类型转换的比较

  • c风格的类型转换一般是直接使用基本内置类型进行转换,c++中定义了4个关键字:static_cast、dynamic_cast、reinpreter_cast、const_cast,用于强制类型转换(cast).
  • 下面举个c style类型转换,c++的几个强制类型转换关键字后面分别介绍。
int i = 3.0;//3.0默认是double类型,强制转换成int
int j = 2;
double k=(double)j;//将int强制转换成double
  • C语言的类型转换通常是不安全的,因为它经常是直接按字节截断的。比如double转换成int就可能不安全,因为int是4字节,double是8字节,截断容易丢失数据。

c++强制类型转换

  • 这里说一下我遇到的问题,就是编程中需要将一个父类指针转换成子类指针。这里我试了static_cast与dynamic_cast都可以成功。所以,就了解到了c++强制类型转换这个东西,借此记录下来。

static_cast与dynamic_cast

MSDN上的一些重要提示。

1、No run-time type check is made to help ensure the safety of the conversion.//
不进行运行时类型检查来帮助确保转换的安全性。
The static_cast operator can be used for operations such as converting a pointer to a base class to a pointer to a derived class. Such conversions are not always safe.//static_cast运算符可用于诸如将指向基类的指针转换为指向派生类的指针之类的操作。这种转换并不总是安全的。
2、In general you use static_cast when you want to convert numeric data types such as enums to ints or ints to floats, and you are certain of the data types involved in the conversion. static_cast conversions are not as safe as dynamic_cast conversions, because static_cast does no run-time type check, while dynamic_cast does. A dynamic_cast to an ambiguous pointer will fail, while a static_cast returns as if nothing were wrong; this can be dangerous. //通常,当你要将数字数据类型(如枚举转换为整数或整数)转换为浮点数时,你可以使用static_cast,并且您确定转换中涉及的数据类型。 static_cast转换不像dynamic_cast转换那样安全,因为static_cast没有运行时类型检查,而dynamic_cast有。对模糊指针的dynamic_cast将失败,而static_cast则返回,就好像没有错误一样;这可能很危险。
3、dynamic_cast conversions are safer, dynamic_cast only works on pointers or references, and the run-time type check is an overhead. See dynamic_cast for more details.//
dynamic_cast转换更安全,dynamic_cast仅适用于指针或引用,运行时类型检查是开销。

  • 总结:dynamic_cast比static_cast更安全;使用static_cast时要做到心中有数。

例子:

class B {};
class D : public B {};
void f(B* pb, D* pd) {
   D* pd2 = static_cast(pb);   // not safe, pb may point to just B
   B* pb2 = static_cast(pd);   // safe conversion
}
  • 第一个转换就是危险的,如果pb指向的是B类的对象,将它强制转换成派生类D的指针pd2,若使用pd2调用派生类D独有的方法,就会出问题。
// static_cast_Operator_2.cpp
// compile with: /LD /GR
class B {
public:
   virtual void Test(){}
};
class D : public B {};
void f(B* pb) {
   D* pd1 = dynamic_cast(pb);
   D* pd2 = static_cast(pb);
}
  • 如果pb真的指向B类对象,pd1和pd2值一样;如果pb指向D类对象,pd1 == NULL,pd2可能被转换成指向D类的指针,因为dynamic_cast有动态类型检查。
// static_cast_Operator_3.cpp
// compile with: /LD /GR
typedef unsigned char BYTE;
void f() {
   char ch;
   int i = 65;
   float f = 2.5;
   double dbl;
   ch = static_cast(i);   // int to char
   dbl = static_cast(f);   // float to double
   i = static_cast(ch);
}
  1. 多字节转换成少字节类型是有风险的,你自己要知道是否有截断风险,有的话转换结果未知。
  2. static_cast不能改变对象的const、volatile、__unaligned 属性。
  3. 若你是用release模式编译,想验证static_cast转换是否正确就要到debug模式下看看结果是否一致。
  • 总结:
    • 在类层次的上行转换(子类->父类)中,static_cast和dynamic_cast效果一样;在类层次的下行转换中(父类->子类),dynamic_cast更安全;
    • dynamic_cast适用局限性,仅适用指针或引用,类型转换是额外开销;static_cast适用于所有,无类型检查额外开销。
    • dynamic_cast要检查转换后指针情况,是否为空;static_cast不需要,但是要心中有数。

reinpreter_cast使用

  • 用法:reinpreter_cast (expression)
  1. 说明:type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。
  2. 可以把int* 转换成char*,即把一种类型指针转换成另一种类型的指针,他们之间是没有继承关系的(One_class* to Unrelated_class*),有继承关系就用上面2种.
  3. 不改变待转换对象的 const, volatile, or __unaligned 属性
  • 例子
	std::vector vecMonitorArray;
	EnumDisplayMonitors(NULL, NULL, &MyInfoEnumProc, reinterpret_cast(&vecMonitorArray));

把wstring类型指针转换成long_ptr.

const_cast用法

  • 用法:const_cast (expression)

说明:该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。

class B{
public:
int m_iNum;
}
void foo(){
const B b1;
b1.m_iNum = 100; //comile error
B b2 = const_cast(b1);
b2. m_iNum = 200; //fine
}
  • 上面的代码编译时会报错,因为b1是一个常量对象,不能对它进行改变;使用const_cast把它转换成一个常量对象,就可以对它的数据成员任意改变。注意:b1和b2是两个不同的对象。

总结

最近经常用这些类型转换,所以借此机会学习一下,了解一下他们的适用范围,注意事项,以后少走弯路.

你可能感兴趣的:(c++学习总结)