假设你有这样的功能:
SmartPtr<A> doSomething(SmartPtr<A> a);
这样的课程:
class A { }
class B : public A { }
现在我这样做:
SmartPtr<A> foo = new B();
doSomething(foo);
现在,我想从SmartPtr<B>
取回doSomething
个对象。
SmartPtr<B> b = doSomething(foo);
有可能吗?我需要做什么样的铸造?
现在,我刚发现了一些我认为丑陋的东西:
B* b = (B*)doSomething().get()
重要说明:我无法访问SmartPtr
和doSomething()
代码。
答案 0 :(得分:8)
而不是这样做,你可以这样做:
B *b = dynamic_cast< B* >( doSomething.get() );
但你必须检查b是否为NULL。
答案 1 :(得分:-1)
您可以定义自己的SmartPtrCast模板功能,其功能如下:
template <typename DestT, typename SrcT>
inline SmartPtr<DestT> SmartPtrCast(const SmartPtr<SrcT> &src)
{
return SmartPtr<DestT>(static_cast<DestT*>(src.get()));
}
然后,你要做的就是从A到B优雅地演绎:
SmartPtr<B> b = SmartPtrCast<B>(doSomething(foo));
警告Emptor:
这只有在doSomething()
返回的智能指针被引用到其他地方时才会起作用,并且当它超出范围时不会被销毁。从你的例子判断,情况确实如此,但它仍然没有那么优雅,应该注意的是两个指针不会共享它们的引用计数(所以如果其中一个被破坏,第二个将失去它的数据)。
更好的解决方案是分离其中一个指针(如果SmartPtr具有分离方法)。一个更好的解决方案(如果你没有分离方法或者你想共享引用计数)是使用包装类:
template <typename SrcT, typename DestT>
class CastedSmartPtr
{
private:
SmartPtr<SrcT> ptr;
public:
CastedSmartPtr(const SmartPtr<SrcT>& src)
{
ptr = src;
}
DestT& operator* () const
{
return *(static_cast<DestT*> >(ptr.get()));
}
DestT* operator->() const
{
return static_cast<DestT*> >(ptr.get());
}
DestT* get() const
{
return static_cast<DestT*> >(ptr.get());
}
}
template <typename DestT, typename SrcT>
inline SmartPtr<DestT> SmartPtrCast(const SmartPtr<SrcT>& src)
{
return CastedSmartPtr<SrcT, DestT>(src);
}
这将在内部使用SmartPtr
(因此引用计数已正确共享),并static_cast
在内部使用DestT
(不会影响性能)。如果要使用dynamic_cast
,则只能在构造函数中执行一次,以避免不必要的开销。您可能还想为包装器添加其他方法,例如复制构造函数,赋值运算符,分离方法等。
答案 2 :(得分:-2)
SmartPtr<B> b = dynamic_cast<B*>(doSomething().get())
或者如果您的SmartPtr支持它,可能会像doSomething().dynamic_cast<B*>()
那样。