在我们想要以某种方式包装Boost Asio套接字的项目中,using类或包装.h不必包含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实际上不是命名空间,而是一个类本身。我们只想使用内部类,任何想法?
答案 0 :(得分: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,因此编译器需要看到该类的定义才能使用它。
答案 1 :(得分: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)
{
}