为什么auto_ptr的dynamic_cast会失败?

时间:2009-02-06 03:24:07

标签: 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;

    }

错误:不能dynamic_cast`(&amp; a) - &gt; std :: auto_ptr&lt; _Tp&gt; :: get()const

5 个答案:

答案 0 :(得分:11)

嗯,std::auto_ptr<B>不是来自std::auto_ptr<A>。但B来自A。 auto_ptr不知道那个(它不是那么聪明)。看起来您想使用共享所有权指针。 boost::shared_ptr是理想的,它还提供了dynamic_pointer_cast:

boost::shared_ptr<A> a = new A();
boost::shared_ptr<B> b = dynamic_pointer_cast<B> (a);

对于auto_ptr,这样的事情无法真正起作用。因为所有权将转移到b。但如果演员表失败,b就无法获得所有权。目前还不清楚该怎么办。您可能不得不说,如果演员表失败,将继续拥有所有权 - 这听起来会导致严重的麻烦。最好开始使用shared_ptr。 ab都会指向同一个对象 - 但Bshared_ptr<B>ashared_ptr<A>

答案 1 :(得分:5)

动态演员不会那样。 A : public B并不意味着auto_ptr<A> : public auto_ptr<B>。这就是提升的shared_ptr提供shared_dynamic_cast的原因。你可以写一个auto_ptr动态演员:

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;

}

请注意这里发生的事情。由于auto_ptr具有所有权语义,因此成功的向下转换意味着原始更通常的类型,auto_ptr不再拥有所有权。

答案 2 :(得分:1)

原因是auto_ptr实际上不是指针。它是一个智能指针,它是一个指针包装器,但实际上并不是指针。作为模板样式参数传递给dynamic_cast的类型必须是真正的指针(或引用)类型。

http://msdn.microsoft.com/en-us/library/cby9kycs(VS.80).aspx

答案 3 :(得分:0)

您正在尝试将A*(由a.get()返回)转换为std::auto_ptr<B>,并且由于第二个甚至不是指针类型,因此失败。可能你只想把它投射到B*

std::auto_ptr<A> a(new A());
std::auto_ptr<B> b(dynamic_cast<B*>(a.get()));

这仍然无法编译,因为AB不是多态类型。 A需要有一个虚函数才能使类型具有多态性。这将编译,但演员阵容将抛出std::bad_cast,因为它不是真正的B*

即使它是B*,如果您尝试使用它,它也会以可怕的方式失败std::auto_ptr s ab都假设他们拥有该对象并在以后释放它,从而导致各种内存损坏。您可能希望在演员表演成功后使用a.release()

答案 4 :(得分:0)

我认为c ++在vtable中存储RTTI(运行时类型信息)。因此,使用dynamic_cast&lt;&gt;对于一个实例对象,该对象需要'vtable'。只有在类中至少有一个函数被声明为'virtual'时,C ++才会创建vtable。

A类和B类没有虚函数。这可能是dynamic_cast失败的原因。尝试在基类中声明一个虚拟析构函数。