Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this dynamic_cast of auto_ptr fail?

Tags:

c++

casting

    #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

like image 766
kal Avatar asked Feb 06 '09 03:02

kal


People also ask

What does dynamic_cast return if fails?

If the dynamic_cast operator succeeds, it returns a pointer that points to the object denoted by arg . If dynamic_cast fails, it returns 0 . You may perform downcasts with the dynamic_cast operator only on polymorphic classes.

Does dynamic_cast need RTTI?

Note. You are permitted to use dynamic_cast without --rtti in cases where RTTI is not required, such as dynamic cast to an unambiguous base, and dynamic cast to (void *) . If you try to use dynamic_cast without --rtti in cases where RTTI is required, the compiler generates an error.

What is the use of dynamic_cast in C++?

In C++, dynamic casting is mainly used for safe downcasting at run time. To work on dynamic_cast there must be one virtual function in the base class. A dynamic_cast works only polymorphic base class because it uses this information to decide safe downcasting.

What does dynamic_cast return in C++?

- lvalue (until C++11)glvalue (since C++11) of a complete class type if new-type is a reference, prvalue of a pointer to complete class type if new-type is a pointer. If the cast is successful, dynamic_cast returns a value of type new-type.


3 Answers

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>

like image 194
Johannes Schaub - litb Avatar answered Oct 10 '22 10:10

Johannes Schaub - litb


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.

like image 23
Logan Capaldo Avatar answered Oct 10 '22 10:10

Logan Capaldo


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

like image 36
JaredPar Avatar answered Oct 10 '22 10:10

JaredPar