2015-04-17 45 views
0

考虑下面的代码:无效初始化错误而上溯造型和向下转换的对象

#include <typeinfo> 
#include<iostream> 

class Parent 
{ 
public: 
    virtual void foo() const{}; 
}; 

class Child_A: public virtual Parent 
{ 
}; 

void downcast(const Child_A& aa) 
{ 
} 

void upcast(const Parent& pp) 
{ 
    std::cout<< typeid(pp).name() << std::endl; 
    downcast(pp); // line 21: This is the problematic line! 
} 


int main() 
{ 
    Child_A aa; 
    upcast(aa); 
    return 0; 
} 

我得到一个编译错误:

initialization.cpp:21:14:错误:的参考无效初始化从类型的表达式 'const的父'

垂头丧气(PP)类型 'const的Child_A &';

但是,如果我编译代码没有行27,typeid(pp).name()返回7Child_A

那么,为什么我会得到这个错误?我该如何解决它?什么是真正的pp

+0

'typeid'是一个运行时操作符。仅仅给出'upcast',编译器不知道'pp'实际上是一个'Child_A'。 – chris

+2

'pp'是对'Parent'的引用。您无法将对“Parent”的引用传递给期望引用“Child_A”的函数。 (并且此代码中没有投射,只是隐式转换。) – molbdnilo

+0

此问题过于复杂,可能会缩减为更小,代表性的示例。 –

回答

3

您在upcast(aa)行上隐式派生到基地的转换。 pp指的是包含在aa中的基类子对象。没有隐式的基于派生的转换。 static_cast可用于执行垂头丧气,但由于Parent是一个虚拟的基础,你将不得不使用dynamic_cast代替:

if (Child_A* c = dynamic_cast<Child_A const*>(&pp)) { 
    downcast(*c); 
} 

typeid(pp).name()返回一个子类输出串线,因为当应用到多态类型的对象(Parent有一个虚拟方法,从而它是多晶型),其结果是最派生类:

When typeid is applied to a glvalue expression whose type is a polymorphic class type (10.3), the result refers to a std::type_info object representing the type of the most derived object (1.8) (that is, the dynamic type) to which the glvalue refers.

注意pp的实际静态类型是Parent const&typeid isn't a very reliable way to get the type of an object.

+0

'static_cast'在这里不起作用。 'Parent'是'Child_A'的虚拟基础。 – Lingxi

+0

@凌熙吧。所以他必须使用'dynamic_cast' – 0x499602D2

3

Downcast不能隐式完成。要纠正它,您可以通过static_castdynamic_cast明确演员。但是,由于ParentChild_A的虚拟基础。这里只适用dynamic_cast。因此,为了使您的代码正确,您可以将downcast(pp);更改为downcast(dynamic_cast<const Child_A&>(pp));。在void upcast(const Parent& pp)内,pp的静态类型为Parent,但其动态类型(实际类型)为Child_Atypeid查询动态类型,这就是为什么7Child_A得到打印。