Reputation: 3859
I was just reading Stroustrup's new book. In Chapter 22.2.2 he discusses a dynamic_cast issue.
The code I have written to test this myself is as follows:
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 explains that c should be a nullptr as it is not possible to know which version of Storable is being referred to. However, I get it as being a valid pointer.
I would guess that Stroustrup is probably correct on this but I cannot see what subtly I have missed, can anyone else spot it?
Upvotes: 4
Views: 250
Reputation: 171097
I can't see ambiguity there. Have you transcribed the example correctly? Quoting C++11, [expr.dynamic.cast]
§8 (using dynamic_cast<C*>(v)
):
... if
v
points (refers) to a public base class subobject of the most derived object, and the type of the most derived object has a base class, of typeC
, that is unambiguous andpublic
, the result points (refers) to theC
subobject of the most derived object.
Your v
is s1
, which points to a Storable
subobject of a most-derived object of type Radio
. There's only one base class subobject of type Component
in Radio
, and it's public, so the dynamic cast should succeed, as it does.
It would be amgiguous if Radio
was derived from Receiver
as well; perhaps you missed that?
Upvotes: 3