Как вы обмениваетесь личными данными с Pimpl, не раскрывая ваши внутренние данные? - PullRequest
3 голосов
/ 09 мая 2011

Если у вас есть объект B, которому нужна копия закрытого члена объекта A, и закрытый член скрыт Pimpl, как вы делаете это без разоблачения ваших внутренних объектов? // Foo.h

class Foo
{
private :
  struct impl ;
  impl * pimpl ;
};

// Foo.cpp
struct impl { std::string data; }

//main.cpp
Foo A;
Foo B;
// I want A::pimpl->data copied to B::pimpl->data and I don't want std::string exposed in my Foo header.

Ответы [ 3 ]

7 голосов
/ 09 мая 2011
// header
class Foo
{
    public:
       void Copy( const Foo & );
    private :
       struct impl ;
       impl * pimpl ;

};

//cpp file
struct impl {std::string data; }

void Foo::Copy( const Foo & f ) {
      pimpl->data = f.pimpl->data;
}
3 голосов
/ 09 мая 2011

Foo необходимо реализовать конструктор, конструктор копирования, деструктор и оператор присваивания, выполняя «правильную вещь» - что позволяет вам делать, например, «A = B;»

// Foo.h
struct FooImpl;
class Foo
{
  Foo(Foo const &);
  Foo();
  ~Foo();
  Foo & operator=(Foo const & RHS);
private:
  FooImpl * pimpl;
};

// Foo.cpp
struct FooImpl {std::string data; }

Foo & Foo::operator=(Foo const & RHS) {
  *pimpl = *RHS.pimpl;
  return *this;
}
Foo::Foo(Foo const & V) {
  pimpl = new FooImpl(*V.pimpl);
}

Foo::Foo() {
  pimpl = new FooImpl;
}

Foo::~Foo() {
  delete pimpl;
}

Теперь вы можете смело делать:

Foo A;
Foo B;
A = B;
0 голосов
/ 09 мая 2011

Помимо других проблем (конструктор копирования и т. Д.), Если вы хотите получить доступ к impl::data без наложения заголовка <string> на все ваши клиенты, вы можете сделать что-то вроде следующего:

// Foo.h
class FooUtil;
class Foo
{
friend class FooUtil;
private :
  struct impl ;
  impl * pimpl ;
};

// FooUtil.h
#include <string>
class FooUtil
{
public:
    static std::string data_of(const Foo&);
};

// Foo.cpp
struct impl { std::string data; }
std::string FooUtil::data_of(const Foo& foo)
{
    return foo.impl->data;
}

//main.cpp
Foo A;
Foo B;

Это обходной путь для использования функции-члена std::string Foo::data() const. Идея заключается в том, что заголовок <string> может быть включен только теми клиентами, которым он нужен.

Отказ от ответственности : мне действительно не нравится этот подход. Это очень не элегантно и вряд ли действительно увеличит время компиляции. Некоторые компиляторы кэшируют (или прекомпилируют) заголовки стандартных библиотек, чтобы помочь людям избежать такого беспорядка.

...