#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
答案 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。 a
和b
都会指向同一个对象 - 但B
为shared_ptr<B>
而a
为shared_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()));
这仍然无法编译,因为A
和B
不是多态类型。 A
需要有一个虚函数才能使类型具有多态性。这将编译,但演员阵容将抛出std::bad_cast
,因为它不是真正的B*
。
即使它是B*
,,如果您尝试使用它,它也会以可怕的方式失败。 std::auto_ptr
s a
和b
都假设他们拥有该对象并在以后释放它,从而导致各种内存损坏。您可能希望在演员表演成功后使用a.release()
。
答案 4 :(得分:0)
我认为c ++在vtable中存储RTTI(运行时类型信息)。因此,使用dynamic_cast&lt;&gt;对于一个实例对象,该对象需要'vtable'。只有在类中至少有一个函数被声明为'virtual'时,C ++才会创建vtable。
A类和B类没有虚函数。这可能是dynamic_cast失败的原因。尝试在基类中声明一个虚拟析构函数。