why dynamic_cast fail here?

P

pietromas

In the example below, why does the dynamic_cast fail (return NULL)? It
should be able to cast between sibling classes ...


#include <iostream>

class A
{
public:
virtual const int get() const = 0;
};

class B : public A
{
public:
virtual const int get() const { return 0; }
};

class C : public A
{
public:
virtual const int get() const { return 1; }
};

int main()
{
A *a;

a = new B();
std::cout << a->get() << std::endl;

a = dynamic_cast<C*>(a);
if(a)
std::cout << a->get() << std::endl;

return 0;
}
 
R

Rolf Magnus

In the example below, why does the dynamic_cast fail (return NULL)?

Because a B is not a C.
It should be able to cast between sibling classes ...

No, it shouldn't. An instance of class B only provides the A interface and
the B interface. So why would you want to access it through the C
interface? What would you expect to happen if C had another member function
and you'd try to call that on your B?
 
P

pietromas

Because a B is not a C.


No, it shouldn't. An instance of class B only provides the A interface and
the B interface. So why would you want to access it through the C
interface? What would you expect to happen if C had another member function
and you'd try to call that on your B?

Yes, I see how that could case problems. So does that mean that the
following is not true (http://www.acm.org/crossroads/xrds3-1/
ovp3-1.html):

"The dynamic_cast Operator

The dynamic_cast operator takes the form

dynamic_cast<T> (expr)

and can be used only for pointer or reference types to navigate a
class hierarchy. The dynamic_cast operator can be used to cast from a
derived class pointer to a base class pointer, cast a derived class
pointer to another derived (sibling) class pointer, or cast a base
class pointer to a derived class pointer. Each of these conversions
may also be applied to references. In addition, any pointer may also
be cast to a void*."

Or else, what are the conditions for casting between sibling classes?
 
R

Rolf Magnus

Yes, I see how that could case problems. So does that mean that the
following is not true (http://www.acm.org/crossroads/xrds3-1/
ovp3-1.html):

"The dynamic_cast Operator

The dynamic_cast operator takes the form

dynamic_cast<T> (expr)

and can be used only for pointer or reference types to navigate a
class hierarchy. The dynamic_cast operator can be used to cast from a
derived class pointer to a base class pointer, cast a derived class
pointer to another derived (sibling) class pointer, or cast a base
class pointer to a derived class pointer. Each of these conversions
may also be applied to references. In addition, any pointer may also
be cast to a void*."

Or else, what are the conditions for casting between sibling classes?

I think it means just that those are the cases where you may use a
dynamic_cast. It might fail (returning a null pointer or throwing an
exception), but you're allowed to use it.
And there is also multiple inheritance:

class A
{
public:
virtual ~A() {}
};

class B
{
public:
virtual ~B() {}
};

class C: public A, public B
{
};

int main()
{
A* a = new C;
B* b = dynamic_cast<B*>(a); // shoulnd't fail
delete b;
}
 
K

Kai-Uwe Bux

In the example below, why does the dynamic_cast fail (return NULL)? It
should be able to cast between sibling classes ...

No, it should not and is not. See [5.2.7] for the conversions supported by
dynamic_cast<>. Specifically [5.2.7/8]

The run-time check logically executes as follows:
? If, in the most derived object pointed (referred) to by v, v points
(refers) to a public base class subobject of a T object, and if only one
object of type T is derived from the sub-object pointed (referred) to by
v, the result is a pointer (an lvalue referring) to that T object.
? Otherwise, if v points (refers) to a public base class sub-object of the
most derived object, and the type of the most derived object has a base
class, of type T, that is unambiguous and public, the result is a
pointer (an lvalue referring) to the T sub-object of the most derived
object.
? Otherwise, the run-time check fails.

#include <iostream>

class A
{
public:
virtual const int get() const = 0;
};

class B : public A
{
public:
virtual const int get() const { return 0; }
};

class C : public A
{
public:
virtual const int get() const { return 1; }
};

int main()
{
A *a;

a = new B();
std::cout << a->get() << std::endl;

a = dynamic_cast<C*>(a);

The dynamic type of *a is B. The dynamic_cast<> is specifically designed to
catch the error in trying to regard this object as anything that it not
truly is. Therefore, dynamic_cast<> will fail if you cast the object to any
type that is not a base class of its dynamic type.

if(a)
std::cout << a->get() << std::endl;

return 0;
}


Best

Kai-Uwe Bux
 
R

Rolf Magnus

Yes, I see how that could case problems. So does that mean that the
following is not true (http://www.acm.org/crossroads/xrds3-1/
ovp3-1.html):

"The dynamic_cast Operator

The dynamic_cast operator takes the form

dynamic_cast<T> (expr)

and can be used only for pointer or reference types to navigate a
class hierarchy. The dynamic_cast operator can be used to cast from a
derived class pointer to a base class pointer, cast a derived class
pointer to another derived (sibling) class pointer, or cast a base
class pointer to a derived class pointer. Each of these conversions
may also be applied to references. In addition, any pointer may also
be cast to a void*."

Or else, what are the conditions for casting between sibling classes?

I think it means just that those are the cases where you may use a
dynamic_cast. It might fail (returning a null pointer or throwing an
exception), but you're allowed to use it.
And there is also multiple inheritance:

class Base
{
public:
virtual ~Base() {}
};

class A : public Base
{
};

class B : public Base
{
};

class C: public A, public B
{
};

int main()
{
A* a = new C;
B* b = dynamic_cast<B*>(a); // shoulnd't fail
delete b;
}
 
P

pietromas

I think it means just that those are the cases where you may use a
dynamic_cast. It might fail (returning a null pointer or throwing an
exception), but you're allowed to use it.
And there is also multiple inheritance:

class A
{
public:
virtual ~A() {}

};

class B
{
public:
virtual ~B() {}

};

class C: public A, public B
{

};

int main()
{
A* a = new C;
B* b = dynamic_cast<B*>(a); // shoulnd't fail
delete b;

}

Okay, thanks for the quick help.
 
R

Rolf Magnus

Okay, thanks for the quick help.

Damn, I wrote a supersede for my posting in the hope that it hadn't already
spread to too many usenet servers, but you were too quick :)
I guess you didn't notice that in my example, the two classes aren't
actually siblings. See my other posting for a better example.
 
S

Sarath

In the example below, why does the dynamic_cast fail (return NULL)? It
should be able to cast between sibling classes ...

#include <iostream>

class A
{
public:
virtual const int get() const = 0;

};

class B : public A
{
public:
virtual const int get() const { return 0; }

};

class C : public A
{
public:
virtual const int get() const { return 1; }

};

int main()
{
A *a;

a = new B();
std::cout << a->get() << std::endl;

a = dynamic_cast<C*>(a);
if(a)
std::cout << a->get() << std::endl;

return 0;}

a points an object which is type of B and you are trying to convert it
to C* it should not work.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top