2011-12-29 50 views
2

我使用boost::intrusive_ptr作爲我的引用計數智能指針。我使用的是這樣的:intrusive_ptr使用ref class的基類幷包含週期地獄

http://www.codeproject.com/KB/stl/boostsmartptr.aspx#intrusive_ptr%20-%20lightweight%20shared%20pointer

這似乎是個好主意,因爲它簡化了新的引用計數類的聲明,從它只是繼承。問題伴隨着前向聲明。有很多地方我想使用指向尚未在類定義中聲明的類型的指針,並且這是不可能的,因爲處理引用計數的2個方法需要知道類型是否從CRefCounted繼承。

如果我試圖在intrusive_ptr的聲明之前包含依賴關係,那就沒問題,但是後來我得到很多循環包含。

你將如何處理這種情況?

+0

稍微偏離主題,但鏈接中存在CRefCounted類的嚴重缺陷,因爲它沒有定義虛擬析構函數。 – Timo 2011-12-29 19:12:48

回答

0

我一直在使用類似的RefCounted基類很多,我開始想知道爲什麼我從來沒有這個問題。這是因爲我傾向於隱藏源文件中的實現細節。考慮B類以下的頭文件:

//File: B.h 
#include <boost/intrusive_ptr.hpp> 

class A; 

class B 
{ 
public: 
    B(); 
    ~B(); 
    boost::intrusive_ptr<A> foo(); 
    void foo2(const boost::intrusive_ptr<A> p); 
    boost::intrusive_ptr<A> p; 
}; 

它的工作原理,因爲即使它使用intrusive_ptr,它並不需要實例構造函數和析構函數。因此它不需要知道關於類A的任何信息。

需要了解A的地方在源文件中。 (並且在foo/foo2被調用的地方)。 B的構造函數和析構函數隱含地調用了A>的構造函數/析構函數,所以A的定義必須可用。

//File: B.cpp 
#include "B.h" 
#include "A.h" //Include header where A is defined. 

B::B() { } 
B::~B() { } 

//Other member functions... 

我不知道如果這能幫助你的情況,但它的一些思考。 :)

+0

好吧,我終於設法解決了它。你的回答讓我走上了正確的道路。我通常做同樣的事情,你暴露。問題是這個愚蠢的蘋果編譯器提供了有關錯誤的錯誤或誤導信息。我提取了項目中的所有文件,並逐個添加它們,問題是類型未完成,只是前向聲明。 – Notbad 2011-12-30 11:53:29

3

我覺得你可以如下解決這個使用模板功能intrusive_ptr_add_refintrusive_ptr_release

namespace boost { 
    template<class T> void intrusive_ptr_add_ref(T* p) { ++(p->references) } 
    template<class T>void intrusive_ptr_release(T* p) { 
    if (--(p->references) == 0) 
     delete p 
    } 
}; 

您還需要在CRefCounted適應朋友的聲明像

template class<T> friend void ::boost::intrusive_ptr_add_ref(T*); 
template class<T> friend void ::boost::intrusive_ptr_release(T*); 

使用這些聲明,您可以使用intrusive_ptr上的前向聲明類,如

class A; 
class B { 
    ::boost::intrusive_ptr<A> _myPtr; 
}; 
class A : public CRefCounted { 
}; 

該解決方案具有以下缺點:(理論上...),您定義的對add_ref/release功能子類的CRefCounted,但我認爲,編譯器會選擇使用內聯無論如何,所以這可能是忽視。

+0

我在發佈之前試過這個解決方案,但沒有解決問題,顯然是因爲編譯器在作弊。感謝您的努力。 – Notbad 2011-12-30 11:54:24