开发者

Handling sequences through C++ class interfaces

Let's sa开发者_高级运维y 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?


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


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> {
    ...
};


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜