背景:我正在为一个不是我编写的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)它不是封装好或直观.
因此,我再问:有没有更好的方法来设计两个私有操纵彼此数据的类?
是的,看看C++朋友.
class B;
class A
{
friend class B;
// ...
};
class B
{
friend class A;
// ...
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
333 次 |
| 最近记录: |