请考虑以下代码:
#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:错误:类型&#39; const Child_A&amp;&#39;的引用无效初始化来自类型&#39; const Parent&#39;
的表达式垂头丧气(PP);
但如果我在没有第27行的情况下编译代码,typeid( pp ).name()
会返回7Child_A
。
那么为什么我会收到此错误?我该如何解决?什么是pp
的真正类型?
答案 0 :(得分:3)
Downcast无法隐式完成。要更正它,您可以通过static_cast
或dynamic_cast
显式转换。但是,由于Parent
是Child_A
的虚拟基础。此处仅适用dynamic_cast
。因此,为了使您的代码更正,您可以将downcast(pp);
更改为downcast(dynamic_cast<const Child_A&>(pp));
。在void upcast( const Parent& pp )
内,pp
的静态类型为Parent
,但其动态类型(实际类型)为Child_A
。 typeid
查询动态类型,这就是7Child_A
被打印的原因。
答案 1 :(得分: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
具有虚方法,因此它是多态的)时,结果是派生类最多的类: / p>
当
typeid
应用于类型为多态类类型(10.3)的glvalue表达式时,结果引用表示最派生对象类型的std::type_info
对象(1.8)(是glvalue引用的动态类型。
请注意,pp
的实际静态类型为Parent const&
。 typeid
isn't a very reliable way to get the type of an object.