通过 C++ 处理序列类接口

发布于 2024-09-18 15:44:22 字数 172 浏览 9 评论 0原文

假设我正在为 A 类编写一个接口,该接口保存 B 类型的对象列表,并且我希望能够通过 A 类的接口来操作该列表。我可以将 add_B、remove_B 等方法放入 A 的接口中,但这会导致大量代码重复(这种情况发生在我的程序中的许多类中),所以我宁愿返回对列表本身的引用。然而,这会破坏封装。
有处理这种情况的标准方法吗?

Let's say I'm writing an interface for a class A that keeps a list of objects of type B, and I want to be able to manipulate that list through class A's interface. I could put add_B, remove_B, etc. methods to A's interface, but that's a lot of code duplication (this situation occurs in many classes in my programme), so I'd rather return a reference to the list itself. That, however, would break encapsulation.
Is there a standard way to handle this situation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

南冥有猫 2024-09-25 15:44:22

下面的代码基于代理设计模式。它通过将接口委托给“代理”对象来保留封装并避免“A”中出现庞大的接口。

另请注意 typedef 如何允许自由地将“列表”更改为“向量”或其他任何内容。

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);
}

The code below is based on the proxy design pattern. It preserves encapsulation and avoids a bulky interface in 'A' by delegating the interface to the 'proxy' object.

Also note how the typedef allows freedom of changing 'list' to 'vector' or anything else.

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);
}
若有似无的小暗淡 2024-09-25 15:44:22

没有足够的信息来给出详细的答案,但从表面上看问题,我认为如果您想限制列表操作或需要维护 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> {
    ...
};

Not enough information to give a detailed answer, but taking the question at face value, I think AddX/RemoveX interface is fine if you want to restrict list operations or need to maintain some other constraint when adding or removing elements.

However, if you frequently need to do complex manipulations on another class' list, maybe it doesn't belong there?

Or use a kind of a mixin class if you just want to remove repetition:

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> {
    ...
};
宣告ˉ结束 2024-09-25 15:44:22

我在目前的发展中也不得不面对同样的情况。我刚刚传递了对该列表的引用。我认为除了你提到的两个之外,没有其他选择。也许您应该创建方法来操作整个列表(add_b、remove_b),并创建一个方法来获取对列表中单个项目的引用以进行项目操作。

顺便说一句:如果您不使用向量来处理对象 B 列表,那么我建议您这样做。

I had to face this very same situation in my current development. I just passed a reference to the list. I don't think there is any other option than the two you mentioned. Perhaps you should make methods to manipulate the whole list (add_b, remove_b) and a method to get a reference to a single item in the list for item manipulation.

BTW: If you are not using vectors to handle your list of object B, then I suggest you do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文