C++ 通过C+处理序列+;类接口
假设我正在为一个类a编写一个接口,该接口保存一个类型为B的对象列表,我希望能够通过类a的接口操作该列表。我可以将add_B、remove_B等方法放在A的接口上,但这会导致大量代码重复(这种情况在我的程序中的许多类中都会发生),因此我宁愿返回对列表本身的引用。然而,这将破坏封装。C++ 通过C+处理序列+;类接口,c++,list,interface,sequence,C++,List,Interface,Sequence,假设我正在为一个类a编写一个接口,该接口保存一个类型为B的对象列表,我希望能够通过类a的接口操作该列表。我可以将add_B、remove_B等方法放在A的接口上,但这会导致大量代码重复(这种情况在我的程序中的许多类中都会发生),因此我宁愿返回对列表本身的引用。然而,这将破坏封装。 有没有一个标准的方法来处理这种情况?在我目前的发展中,我不得不面对同样的情况。我刚刚传递了对列表的引用。我认为除了你提到的两个,没有其他选择。也许您应该创建一个方法来操作整个列表(add_b,remove_b)和一个方
有没有一个标准的方法来处理这种情况?在我目前的发展中,我不得不面对同样的情况。我刚刚传递了对列表的引用。我认为除了你提到的两个,没有其他选择。也许您应该创建一个方法来操作整个列表(add_b,remove_b)和一个方法来获取对列表中单个项的引用以进行项操作
顺便说一句:如果你没有使用向量来处理对象B的列表,那么我建议你这样做。没有足够的信息来给出详细的答案,但是从表面上看问题,我认为
AddX
/RemoveX
如果您想要限制列表操作,或者在添加或删除元素时需要维护一些其他约束,那么界面就可以了
然而,如果您经常需要对另一个类的列表进行复杂的操作,那么它可能不属于那里
如果您只想删除重复,请使用一种mixin类:
template<class T>
class ListOf {
public:
// Public interface only allows adding or removal.
typedef boost::shared_ptr<T> Ptr;
void Add(const Ptr &elem) {
elems_.insert(elem);
}
void Remove(const Ptr &elem) {
elems_.erase(elem);
}
protected:
// Subclass can access container reference.
typedef std::set<Ptr> ElemSet;
ElemSet& Elements() {
return elems_;
}
const ElemSet& Elements() const {
return elems_;
}
private:
ElemSet elems_;
};
class Foo : public Bar, public ListOf<Baz> {
...
};
模板
类列表{
公众:
//公共接口仅允许添加或删除。
typedef boost::shared_ptr ptr;
无效添加(常量Ptr&elem){
元素插入(元素);
}
无效删除(常数Ptr&elem){
元素擦除(elem);
}
受保护的:
//子类可以访问容器引用。
typedef std::set ElemSet;
元素集和元素(){
返回元素;
}
常量ElemSet&Elements()常量{
返回元素;
}
私人:
元素集元素;
};
Foo类:公共酒吧、公共列表{
...
};
以下代码基于代理设计模式。通过将接口委托给“代理”对象,它保留了封装并避免了“a”中庞大的接口
还要注意typedef如何允许将“list”更改为“vector”或其他任何内容
struct B{};
struct A{
struct containerproxy{
void Add(B *pb);
void Remove(B *pb);
};
friend struct containerproxy;
containerproxy &GetProxy(){return mlprx;}
typedef containerproxy intf;
~A(){
// Code to delete list elements and cleanup the list
}
private:
containerproxy mlprx;
list<B*> mlp;
};
void A::containerproxy::Add(B *pb){ /*code to add pb to mlp*/}
void A::containerproxy::Remove(B *pb){/*code to remove pb from mlp*/}
int main(){
A a;
A::intf &r = a.GetProxy();
B *p = new B;
r.Add(p);
}
结构B{};
结构A{
结构容器代理{
无效添加(B*pb);
脱空(B*pb);
};
friend struct containerproxy;
containerproxy&GetProxy(){return mlprx;}
typedef containerproxy intf;
~A(){
//用于删除列表元素并清理列表的代码
}
私人:
containerproxy mlprx;
名单mlp;
};
void A::containerproxy::添加(B*pb){/*将pb添加到mlp的代码*/}
void A::containerproxy::Remove(B*pb){/*从mlp中删除pb的代码*/}
int main(){
A A;
A::intf&r=A.GetProxy();
B*p=新的B;
r、 加(p);
}
std::list也不错。似乎大多数人都会跳转到向量:)@Merlyn,链表在大多数情况下通常更糟糕,因为大多数时候你处理的是一个由几个,最多十几个元素组成的列表,所以向量的插入/删除速度不是问题,而且它们的缓存命中率也要高得多,与链表不同,转发/执行适配器模式并不是真正不受欢迎的,代码复制是明智的。代码复制最糟糕的部分是当您有创建多个维护点的代码时,您可能会得到多个代码略有不同的副本。这种情况对于进行维护编程的人来说可能并不明显,这正是令人头痛的地方:)小心地在类A上提供有用的功能,避免转发列表的每个方法,除非这样做很有意义。我喜欢这种解决方案。不过,我会将代理实现为一个独立的类(因为我将在许多地方使用它)。谢谢