3

如果您有一个对象 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.
4

3 回答 3

7
// 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;
}
于 2011-05-09T12:23:46.547 回答
3

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;
于 2011-05-09T12:24:44.313 回答
0

除了其他问题(复制构造函数等),如果您想在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成员函数的 hack-ish 解决方法。这个想法是您可以<string>只让需要它的客户包含标题。

免责声明:我真的不喜欢这种方法。它非常不优雅,不太可能真正增加编译时间。一些编译器缓存(或预编译)标准库头文件,以帮助人们避免这种混乱。

于 2011-05-09T12:50:42.380 回答