2011-12-29 45 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