Обработка последовательностей через интерфейсы класса C ++ - PullRequest
2 голосов
/ 11 сентября 2010

Допустим, я пишу интерфейс для класса A, в котором хранится список объектов типа B, и я хочу иметь возможность манипулировать этим списком через интерфейс класса A.Я мог бы добавить методы add_B, remove_B и т. Д. В интерфейс A, но это много дублирует код (такая ситуация встречается во многих классах в моей программе), поэтому я бы предпочел вернуть ссылку на сам список.Это, однако, нарушит инкапсуляцию.
Есть ли стандартный способ справиться с этой ситуацией?

Ответы [ 3 ]

1 голос
/ 11 сентября 2010

Недостаточно информации, чтобы дать подробный ответ, но, принимая вопрос за чистую монету, я думаю, что интерфейс 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> {
    ...
};
1 голос
/ 11 сентября 2010

Приведенный ниже код основан на шаблоне дизайна прокси.Он сохраняет инкапсуляцию и избегает громоздкого интерфейса в «A», делегируя интерфейс объекту «proxy».

Также обратите внимание, как 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);
}
0 голосов
/ 11 сентября 2010

Мне пришлось столкнуться с той же самой ситуацией в моем текущем развитии. Я только что передал ссылку на список. Я не думаю, что есть какой-то другой вариант, кроме двух, которые вы упомянули. Возможно, вам следует создать методы для манипулирования всем списком (add_b, remove_b) и метод для получения ссылки на один элемент в списке для манипулирования элементами.

Кстати: если вы не используете векторы для обработки списка объектов B, я предлагаю вам сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...