假设我有一个类MainApp使用动态库的方法通过接口FrontEnd
FrontEnd使用类Data的内部实例(包含在BackEnd类中)
此类Data仅包含成员及其访问者,没有公共方法来操作成员
好了,现在MainApp不了解数据,也无法访问数据,但需要间接操作它
我的目标是创建某种引用,保持指向具有2个行为的数据的指针
我列出了一些解决方案,如PIMPL习惯用法,桥接器或适配器模式,但问题是我不想像参考界面那样使用参考,但就像持有者一样
我该如何处理?
这里有一些代码来说明:
struct Data {
Data(int i):member(i){}
int getMember();
private :
int member;
};
#include "Data.hpp"
struct BackEnd {
BackEnd(){}
Data* createData(int i) {
Data* d = new Data(i);
mDatas.push_back(d);
return d;
}
void doSomething(Data* d, int param) {
int r = param+d->getMember();
/*do other things with d*/
}
private:
vector<Data*> mDatas;
};
#include //???
struct Reference {
Reference(Data* d):mData(d){}
private:
//no access to data->member
Data* mData;
};
#include "Data.hpp"
#include "Reference.hpp"
#include "BackEnd.hpp"
struct FrontEnd {
Reference* createData(int i) {
Data* d = mBackEnd->createData(i);
//conversion Data to Reference
Reference ref = new Reference(d);
return ref;
}
void doSomething(Reference* ref) {
//In the Front-End, I want an access to Ref->mData
Data* d = ref->getData();//Allows access to Ref->mData
int result = mBackEnd->doSomething(d);
}
private:
BackEnd* mBackEnd;
};
//I don't want to reference Data.hpp
#include "Reference.hpp"
#include "FrontEnd.hpp"
struct MainApp {
Reference* createRef(){ mRef = mFrontEnd->createData(8);}
void doSomething(){ mFrontEnd->doSomething(mRef); }
private:
FrontEnd* mFrontEnd;
Reference* mRef;
//I want to keep a reference to Data without using Data directly
//Forbids access to mRef->mData
};
答案 0 :(得分:2)
如果您想允许外部类访问另一个内部的内部,您可以将其设置为friend
。
struct Foo;
struct Bar {
private:
friend struct Foo;
int count;
};
struct Foo {
void doBarStuff(Bar &bar) {
bar.count = 2;
}
};
这显然是一种折衷。可以不同地考虑这两种结构,但如果它们相互接触,则它们没有太多关注点。谨慎使用。
执行此操作时,最好通过方法调用访问内部,而不是直接操作它们。看起来你似乎在增加复杂性,而且你在某种程度上也是如此。但是,它会使您的访问意图变得清晰。
struct Foo;
struct Bar {
private:
friend struct Foo;
void setCount(int c) {
if (count < 0)
throw std::logic_error("out of range");
count = c;
}
int count;
};
struct Foo {
void doBarStuff(Bar &bar) {
bar.setCount(2);
}
};
例如,您不希望在Foo
中遍布计数检查。
答案 1 :(得分:2)
考虑使用友情 - 即FrontEnd
friend
Reference
protected
,这样您就可以在Reference
中拥有Data*
成员,这样您就可以得到Reference.h
。在FrontEnd.h
中,包含FrontEnd.h
(以允许友谊),在Reference
中,使用FrontEnd
作为前向声明(即不包括标题)。仅在FrontEnd.h
的实现文件中包含标头。您必须将所有定义(在MyApp
中)移动到实现文件中。
现在Reference
可以很高兴地拥有Data*
但FrontEnd
只能通过{{1}}获得。