我刚读了Stroustrup的新书。在第22.2.2章中,他讨论了dynamic_cast问题。
我自己编写的代码如下:
class Storable
{
public:
int i;
virtual void r() {};
Storable()
{
i = 1;
};
};
class Component:public virtual Storable
{
public:
Component()
{
i = 1;
};
};
class Receiver:public Component
{
public:
Receiver()
{
i = 2;
};
};
class Transmitter:public Component
{
public:
Transmitter()
{
i = 3;
};
};
class Radio:public Transmitter
{
public:
Radio()
{
i = 4;
};
};
int _tmain(int argc, _TCHAR* argv[])
{
Radio *r = new Radio();
Storable *s1 = dynamic_cast<Storable*>(r);
Component *c = dynamic_cast<Component*>(s1); // this should be 0 but it is not!
return 0;
}
Stroostrup解释说c应该是一个nullptr,因为无法知道哪个版本的Storable被引用。但是,我认为它是一个有效的指针。
我猜想Stroustrup在这方面可能是正确的,但是我看不出有什么巧妙的错过,其他人可以发现它吗?
答案 0 :(得分:3)
我不能在那里看到歧义。你有正确的转录例子吗?引用C ++ 11,[expr.dynamic.cast]
§8(使用dynamic_cast<C*>(v)
):
...如果
v
指向(引用)最派生对象的公共基类子对象,并且派生程度最大的对象的类型具有类型为C
的基类,则是明确的public
,结果指向(引用)最派生对象的C
子对象。
您的v
是s1
,它指向Storable
类型最派生的对象的Radio
子对象。 Component
中只有一个类型为Radio
的基类子对象,并且它是公共的,因此动态转换应该成功,就像它一样。
如果Radio
也来自Receiver
,那将是很明显的;也许你错过了?