开发者

How do you exchange private data with Pimpl without exposing your internals?

开发者 https://www.devze.com 2023-03-04 03:36 出处:网络
If you have an object B that needsa copy of a private member of 开发者_运维技巧an object A, and the private member is hidden by a Pimpl, how do you make it happen without exposing your internals?

If you have an object B that needs a copy of a private member of 开发者_运维技巧an object A, and the private member is hidden by a Pimpl, how do you make it happen without exposing your internals? // 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.


// 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;
}


Foo needs to implement a constructor, a copy constructor, a destructor and an assignment operator, doing the "right thing" - allowing you to do e.g. '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;
}

Now you can safely do:

Foo A;
Foo B;
A = B;


Other issues aside (copy constructor, ec.), if you want to access impl::data without imposing the <string> header to all your clients, you can do something like the following:

// 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;

This is a hack-ish work-around for having a std::string Foo::data() const member function. The idea is that you can have the <string> header included by only the clients who need it.

Disclaimer: I really don't like this approach. It's very inelegant and is unlikely to really increase compile times. Some compilers cache (or pre-compile) standard library headers so as to help people avoid this kind of mess.

0

精彩评论

暂无评论...
验证码 换一张
取 消