有没有办法设计两个私有操纵彼此数据的类?

Low*_*eek 2 c++ class-design

背景:我正在为一个不是我编写的C库编写C++包装器接口.我的包装类模仿了库结构,在这个库中,有些成员struct b指向了成员struct a.该库的文档说:"不要销毁struct a之前的变量struct b." 实际上应该允许这样的情况,所以我想在代码中更好地处理这种情况.因此,在我的包装器中,如果class A有一个或多个class B指向它的实例的实例在B的所有实例之前被销毁,我想将数据从A复制到B的每个实例.目前,我用公共处理这个成员函数,如下:

// some code shortened or not shown

struct a {
  int d;                            // in reality, data is much more complicated
};
struct b {
  int* d;
};

class B;
class A {
  struct a a_;
  vector<B*> registered_bs_;                // should probably use unordered_set
public:
  ~A(void) { for (iterator it: registered_bs_) (*it)->copyA(); }    // C++0x for
  void registerB(B* b)   { registered_bs_.push_back(b); }
  void unregisterB(B* b) { registered_bs_.erase(b); }   // find() code not shown
};

class B {
  struct b b_;
  A* pa_;
public:
  B(A& a): b_(), pa_(0) { a.registerB(this); pa_ = &a; }
  ~B(void) { pa_->unregisterB(this); if (b_.d) delete b_.d; } // if B goes first
  void copyA(void) { b_.d = new int(*b_.d); }
};
Run Code Online (Sandbox Code Playgroud)

如可从上文中,寄存器可以看出和复制部件功能只与只能从构造函数/ dtors调用.换句话说,我的类的用户永远不应该调用这些函数.因此,根据封装原则和Scott Meyer的"使接口易于正确使用且难以正确使用"的理念,我想将这些功能放在A和B的私有部分中.但是,这显然意味着我再也无法从他们的同伴班级中调用他们了.我考虑过使用friend函数,如下:

// this doesn't work

class B;
class A {
  struct a a_;
  vector<B*> registered_bs_;

  void copyA(B& b) { b.b_.d = new int(*(b.b_.d)); }                 // circular
  friend void B::registerB(A& a);                                   // circular
  friend void B::unregisterB(A& a);                                 // circular
public:
  ~A(void) { for (iterator it: registered_bs_) copyA(*it); }       // C++0x for
};

class B {
  struct b b_;
  A* pa_;

  void registerB(A& a)   { a.registered_bs_.push_back(this); }
  void unregisterB(A& a) { a.registered_bs_.erase(this); }  // find() not shown
  friend void A::CopyA(B& b);
public:
  B(A& a): b_(), pa_(0) { registerB(a); pa_ = &a; }
  ~B(void) { unregisterB(*pa_); if (b_.d) delete b_.d; }
};
Run Code Online (Sandbox Code Playgroud)

但是,这段代码至少有三个问题:1)有一个无法解决的循环关系,2)每个类仍在尝试访问friend声明中其他类的私有成员,3)它不是封装好或直观.

因此,我再问:有没有更好的方法来设计两个私有操纵彼此数据的类?

And*_*ron 7

是的,看看C++朋友.

class B;

class A
{
    friend class B;
    // ...
};

class B
{
    friend class A;
    // ...
};
Run Code Online (Sandbox Code Playgroud)

C++ FAQ 对友谊有一个很好的解释.

  • +1,当两个类需要真正紧密耦合时,他们成为朋友通常比在公共范围内暴露超出必要的功能更好. (2认同)