0

在一个项目中,我们希望以某种方式包装 Boost Asio 套接字,使用类或包装 .h 不必包含 boost 标头。

我们通常对包装类使用指针和前向声明。

转发声明:

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 实际上不是命名空间,而是一个类本身。我们只想使用内部类,有什么想法吗?

4

2 回答 2

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.

要回答您的具体问题,您尝试使用的类型是 asio udp 类中的 typedef,因此编译器需要查看该类的定义才能使用它。

于 2009-10-28T03:35:01.720 回答
2

对于内部类型,您唯一的选择是包装所有内容。将作用域指针本身隐藏在前向声明的类中。用户只会看到您的 API 并传递您自己的对象而不是 boost 对象。

在您的示例中,虽然 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)
{ 
}
于 2009-10-28T03:35:41.203 回答