Вопрос

в проекте мы хотим обернуть сокет Boost Asio таким образом, чтобы класс using или оболочка .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 на самом деле не пространство имен, а сам класс. Мы хотим использовать только внутренний класс, есть идеи?

Это было полезно?

Решение

С внутренними типами ваш единственный вариант - обернуть все. Спрячьте указатели с областью видимости внутри заранее объявленного класса. Пользователи увидят только ваш 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)
{ 
}

Другие советы

Если вы используете 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.

Чтобы ответить на ваш конкретный вопрос, типами, которые вы пытаетесь использовать, являются typedefs в классе asio udp, поэтому компилятор должен видеть определение этого класса, чтобы использовать его.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top