tags:

views:

697

answers:

5
    #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

+1  A: 

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

JaredPar
+8  A: 

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>

Johannes Schaub - litb
+3  A: 

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_ptrs have ownership semantics, a successful downcast means the original more generally typed, auto_ptr no longer has ownership.

Logan Capaldo
A: 

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_ptrs 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.

sth
A: 

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.

Nitin Bhide