By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,134 Members | 1,742 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,134 IT Pros & Developers. It's quick & easy.

why dynamic_cast fail here?

P: n/a
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;
}

Mar 15 '07 #1
Share this Question
Share on Google+
8 Replies


P: n/a
pi*******@gmail.com wrote:
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?
#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;
}
Mar 15 '07 #2

P: n/a
On Mar 15, 12:12 pm, Rolf Magnus <ramag...@t-online.dewrote:
pietro...@gmail.com wrote:
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?
#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;
}
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?

Mar 15 '07 #3

P: n/a
pi*******@gmail.com wrote:
On Mar 15, 12:12 pm, Rolf Magnus <ramag...@t-online.dewrote:
>pietro...@gmail.com wrote:
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?
#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;
}

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;
}

Mar 15 '07 #4

P: n/a
On Mar 15, 12:37 pm, Rolf Magnus <ramag...@t-online.dewrote:
pietro...@gmail.com wrote:
On Mar 15, 12:12 pm, Rolf Magnus <ramag...@t-online.dewrote:
pietro...@gmail.com wrote:
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?
#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;
}
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;

}
Okay, thanks for the quick help.

Mar 15 '07 #5

P: n/a
pi*******@gmail.com wrote:
On Mar 15, 12:12 pm, Rolf Magnus <ramag...@t-online.dewrote:
>pietro...@gmail.com wrote:
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?
#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;
}

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;
}

Mar 15 '07 #6

P: n/a
pi*******@gmail.com wrote:
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
Mar 15 '07 #7

P: n/a
pi*******@gmail.com wrote:
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.

Mar 15 '07 #8

P: n/a
On Mar 15, 8:51 pm, pietro...@gmail.com wrote:
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.

Mar 15 '07 #9

This discussion thread is closed

Replies have been disabled for this discussion.