2009-10-28 3 views
0

в проекте, который мы хотим обернуть сокет Boost Asio таким образом, чтобы используемый класс или обертывание .h не включали заголовки boost.Можно ли обмотать розетки с помощью Pimpl?

Обычно мы используем указатели и форвардные объявления для обернутых классов.

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

+0

Зависит от того, что имеет смысл. Обычно я использую класс pimpl как ведомый элемент данных (также он обычно является структурой), к которому осуществляется хост-класс точно так же, как если бы он был собственным. Но я ленив. :) – Eugene

+0

janm ниже говорит о том же самом BTW. – Eugene

3

Если вы используете pimpl, то почему вы помещаете переменные-члены в свой заголовок? Используются ли сокеты и конечные точки typedefs в вашем интерфейсе? Если они не являются частью вашего интерфейса, вся точка идиомы 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, поэтому компилятор должен был увидеть определение этого класса для его использования.