Reputation: 29381
#include "iostream"
class A {
private:
int a;
public :
A(): a(-1) {}
int getA() {
return a;
}
};
class A;
class B : public A {
private:
int b;
public:
B() : b(-1) {}
int getB() {
return b;
}
};
int main() {
std::auto_ptr<A> a = new A();
std::auto_ptr<B> b = dynamic_cast<std::auto_ptr<B> > (a);
return 0;
}
ERROR: cannot dynamic_cast `(&a)->std::auto_ptr<_Tp>::get() const
Upvotes: 6
Views: 2982
Reputation: 1695
I think c++ stores RTTI (run time type information) in the vtable. Hence to use dynamic_cast<> with an instance object, the object needs have 'vtable'. C++ creates vtable only when at least one function is declared 'virtual' in the class.
The class A and Class B there are no virtual functions. This could be reason for the dynamic_cast failure. Try declaring a virtual destructor in base class.
Upvotes: 0
Reputation: 40336
dynamic cast doesn't work that way. A : public B
does not imply auto_ptr<A> : public auto_ptr<B>
. This is why boost's shared_ptr
provides shared_dynamic_cast
. You could write an auto_ptr
dynamic cast though:
template<typename R, typename T>
std::auto_ptr<R> auto_ptr_dynamic_cast(std::auto_ptr<T>& in) {
auto_ptr<R> rv;
R* p;
if( p = dynamic_cast<R*>( in.get() ) ) {
in.release();
rv = p;
}
return rv;
}
Just be aware of what happens here. Since auto_ptr
s have ownership semantics, a successful downcast means the original more generally typed, auto_ptr no longer has ownership.
Upvotes: 5
Reputation: 229663
You're trying to cast a A*
(returned by a.get()
) to std::auto_ptr<B>
, and since the second is not even a pointer type this fails. Probably you just want to cast it to B*
:
std::auto_ptr<A> a(new A());
std::auto_ptr<B> b(dynamic_cast<B*>(a.get()));
This will still not compile, because A
and B
aren't polymorphic types. A
needs to have a virtual function in order to make the types polymorphic. This will compile, but the cast will just throw std::bad_cast
, since it isn't really a B*
.
And even if it were a B*
, it will fail in horrendous ways if you try to use it. Both std::auto_ptr
s a
and b
will assume they own the object and free it later on, resulting in all kinds of memory corruption. You probably want to use a.release()
after the cast was successful.
Upvotes: 0
Reputation: 507055
Well, std::auto_ptr<B>
is not derived from std::auto_ptr<A>
. But B
is derived from A
. The auto_ptr does not know about that (it's not that clever). Looks like you want to use a shared ownership pointer. boost::shared_ptr
is ideal, it also provides a dynamic_pointer_cast:
boost::shared_ptr<A> a = new A();
boost::shared_ptr<B> b = dynamic_pointer_cast<B> (a);
For auto_ptr, such a thing can't really work. Because ownership will move to b
. But if the cast fails, b can't get ownership. It's not clear what to do then to me. You would probably have to say if the cast fails, a will keep having the ownership - which sounds like it will cause serious trouble. Best start using shared_ptr. Both a
and b
then would point to the same object - but B
as a shared_ptr<B>
and a
as a shared_ptr<A>
Upvotes: 11
Reputation: 754893
The reason is that auto_ptr is not actually a pointer. It's a smart pointer which is a pointer wrapper but not actually a pointer. The type that is passed as a template style argument to dynamic_cast must be a true pointer (or reference) type.
http://msdn.microsoft.com/en-us/library/cby9kycs(VS.80).aspx
Upvotes: 1