2009-10-28 73 views
0

在一个项目中,我们想要以某种方式包装Boost Asio套接字,使用类或包装.h不必包含boost头文件。是否可以用Pimpl封装boost套接字?

我们通常使用包装类的指针和转发声明。

FOWARD声明:

namespace boost 
{ 
    namespace asio 
    { 
    namespace ip 
    { 
     class udp; 
    } 
    } 
} 

然后宣布插座:

scoped_ptr<boost::asio::ip::udp::socket> socket_; 
    scoped_ptr<boost::asio::ip::udp::endpoint> receiveEp_; 

(如果你不知道scoped_ptr的,忽略它,这个问题是一个标准的*指针相等)。

但是,这给出了一个编译器错误:

error C2027: use of undefined type 'boost::asio::ip::udp' 

我明白这是因为udp实际上不是一个命名空间,而是一个类本身。我们只想使用内部类,任何想法?

回答

2

对于内部类型你唯一的选择是包装一切。将范围指针本身隐藏在一个前向声明的类中。用户只会看到你的API并传递你自己的对象而不是提升对象。

在你的榜样,虽然scoped_ptr的样子私有成员声明,​​你可以逃脱简单:

// header 
class SomeClass 
{ 
public: 
    SomeClass(); 
    // stuff 
private: 
    scoped_ptr<class pimpl_bla> _m; 
}; 

// source 
class pimpl_bla 
{ 
public: 
    scoped_ptr<boost::asio::ip::udp::socket> socket_; 
}; 

SomeClass::SomeClass() 
    :_m(new pimpl_bla) 
{ 
} 
+0

也就是说,我将不得不定义所有的公共职能两次..和SomeClass的将简单地把它们传递给pimpl_bla ? – Tarnschaf 2009-10-28 03:47:43

+0

取决于什么是有道理的。我通常使用pimpl类作为数据成员存储桶(也通常是一个结构体),它们可以通过与宿主类完全相同的方式访问,就像它们是它自己的一样。但我很懒。 :) – Eugene 2009-10-28 04:32:02

+0

下面谈谈完全相同的事情顺便说一句。 – Eugene 2009-10-28 04:33:32

3

如果您使用的是pimpl,为什么要将成员变量放在标题中?您的界面中使用了套接字和端点类型定义?如果它们不是你的接口的一部分,pimpl习语的全部意义在于你没有在头文件中定义一个类的成员变量;他们是实施细节。

我希望在头文件是这样的:

// ... 

class MyClass { 
public: 
    MyClass(); 
    // .. Other member functions 

private: 
    struct Imp; 
    boost::shared_ptr<Imp> m_imp; // This is the only member variable. 
}; 

,然后在实现文件:

#include <boost/asio/whatever.hpp> 

struct MyClass::Imp 
{ 
    scoped_ptr<boost::asio::ip::udp::socket> socket_; 
    scoped_ptr<boost::asio::ip::udp::endpoint> receiveEp_; 

    // Remainder of implementation class ... 
}; 

// Other implementation details. 

为了回答您的具体问题,你要使用的类型的typedef在asio udp类中,编译器需要看到该类的定义才能使用它。

相关问题