2010-04-22 122 views
19
using namespace boost; 

class A {}; 
class B : public A {}; 

class X { 
    virtual shared_ptr<A> foo(); 
}; 

class Y : public X { 
    virtual shared_ptr<B> foo(); 
}; 

返回類型不是協變的(它們也不合法),但是如果我使用原始指針而不是合法的。如果有的話,什麼是解決這個問題的普遍接受的習慣用法?如何在返回shared_ptr時完成協變返回類型?

+1

http://stackoverflow.com/questions/196733/how-can-i-use-covariant-return-types-with-smart-pointers – 2010-04-22 02:12:37

回答

11

我認爲一個解決方案根本不可能,因爲協方差依賴於與智能指針不兼容的指針算術。

Y::fooshared_ptr<B>返回給動態調用者時,它必須在使用前轉換爲shared_ptr<A>。在你的情況下,一個B*可能(可能)簡單地被重新解釋爲A*,但對於多重繼承,你需要一些魔法才能告訴C++關於static_cast<A*>(shared_ptr<B>::get())

+0

可能的副本嗯,「根本上」協方差取決於轉換,也許應該使用隱式可轉換類型。但是這仍然不適用於'shared_ptr'。 – Potatoswatter 2012-08-16 05:51:10

+0

「_But仍然不適用於'shared_ptr'_」我不明白:是否'shared_ptr'不可轉換? – curiousguy 2013-05-28 13:50:51

+0

@curiousguy哦,它是哎呀。仍然只是一個假設。 – Potatoswatter 2013-05-29 07:21:58

4

不是直接的,但是你可以通過使虛擬函數在類外部不可訪問並將虛擬函數調用包裝爲非虛函數來僞裝它。缺點是你必須記得在每個派生類上實現這個包裝函數。但是你可以通過把這個virtul函數聲明和包裝器放到宏中來解決這個問題。

using namespace boost; // for shared_ptr, make_shared and static_pointer_cast. 

// "Fake" implementation of the clone() function. 
#define CLONE(MyType) \ 
    shared_ptr<MyType> clone() \ 
    { \ 
     shared_ptr<Base> res = clone_impl(); \ 
     assert(dynamic_cast<MyType*>(res.get()) != 0); \ 
     return static_pointer_cast<MyType>(res); \ 
    } 

class Base 
{ 
protected: 
    // The actual implementation of the clone() function. 
    virtual shared_ptr<Base> clone_impl() { return make_shared<Base>(*this); } 

public: 
    // non-virtual shared_ptr<Base> clone(); 
    CLONE(Base) 
}; 

class Derived : public Base 
{ 
protected: 
    virtual shared_ptr<Base> clone_impl() { return make_shared<Derived>(*this); } 

public: 
    // non-virtual shared_ptr<Derived> clone(); 
    CLONE(Derived) 
}; 


int main() 
{ 
    shared_ptr<Derived> p = make_shared<Derived>(); 
    shared_ptr<Derived> clone = p->clone(); 

    return 0; 
} 
+0

已經有一段時間了,因爲這已經回答了。既然C++ 11已經出來了,有沒有更好的方法? – 2014-07-28 23:12:07

+0

@CoryBeutler。不,如果你想使用shared_ptr。如果你願意放棄shared_ptr並願意使用侵入式引用計數,那麼是的。在這種情況下,這些函數將返回原始指針並獲得自動重新計數,您只需將結果分配給智能指針(例如boost :: intrusive_ptr)即可。 – lego 2014-07-29 10:53:23

-1

我只是返回一個裸指針並立即將其包裝在共享指針中。

+0

你幾乎從不想將別人的裸指針包裝到shared_ptr。 – ShitalShah 2016-12-21 04:01:21