深入解析C++中的动态类型转换与静态类型转换运算符

2020-01-06 14:20:39刘景俊

此转换类型称为“向下转换”,因为它将在类层次结构下的指针,从给定的类移到该类派生的类。
对于多重继承,引入多义性的可能性。考虑下图中显示的类层次结构。
对于 CLR 类型,如果转换可以隐式执行,则 dynamic_cast 结果为 no-op,如果转换失败,则 MSIL isinst 指令将执行动态检查并返回 nullptr。
以下示例使用 dynamic_cast 以确定一个类是否为特殊类型的实例:


// dynamic_cast_clr.cpp
// compile with: /clr
using namespace System;

void PrintObjectType( Object^o ) {
  if( dynamic_cast<String^>(o) )
   Console::WriteLine("Object is a String");
  else if( dynamic_cast<int^>(o) )
   Console::WriteLine("Object is an int");
}

int main() {
  Object^o1 = "hello";
  Object^o2 = 10;

  PrintObjectType(o1);
  PrintObjectType(o2);
}

显示多重继承的类层次结构
显示多继承的类层次结构
指向类型 D 对象的指针可以安全地强制转换为 B 或 C。但是,如果 D 强制转换为指向 A 对象的指针,会导致 A 的哪个实例?这将导致不明确的强制转换错误。若要避免此问题,可以执行两个明确的转换。例如:


// dynamic_cast_4.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};
class D : public B {virtual void f();};

void f() {
  D* pd = new D;
  B* pb = dynamic_cast<B*>(pd);  // first cast to B
  A* pa2 = dynamic_cast<A*>(pb);  // ok: unambiguous
}

当使用虚拟基类时,其他多义性问题会被引入。考虑下图中显示的类层次结构。

深入解析C++中的动态类型转换与静态类型转换运算符

显示虚拟基类的类层次结构
在此层次结构中,A 是虚拟基类。对于虚拟基类的定义。给定一个 E 类实例和一个指向 A 子对象的指针,指向 B 指针的 dynamic_cast 将失败于多义性。必须先将强制转换回完整 E 对象,然后以明确的方式反向沿层次结构,到达正确的 B 对象。
考虑下图中显示的类层次结构。

深入解析C++中的动态类型转换与静态类型转换运算符