Последовательная итерация нескольких списков (C ++) - PullRequest
2 голосов
/ 23 мая 2010

У меня есть 3 класса, 2 наследуются от других, вот так:

class A {
  public:
    virtual void foo() {cout << "I am A!" << endl;}
};

class B : public A {
  public:
    void foo() {cout << "B pretending to be A." << endl}
    void onlyBFoo() {cout << "I am B!" << endl}
};

class C : public A {
  public:
    void foo() {cout << "C pretending to be A." << endl}
    void onlyCFoo() {cout << "I am C!" << endl}
};

Что я хочу сделать, это примерно так:

list<A*> list_of_A;
list<B*> list_of_B;
list<C*> list_of_C;

//put three of each class in their respective list

cout << "First loop:" << endl;
for (list<B>::iterator it = list_of_B.begin(); it != list_of_B.end(); ++it) {
  (*it)->onlyBFoo();
}

cout << "Second loop:" << endl;
for (list<C>::iterator it = list_of_C.begin(); it != list_of_C.end(); ++it) {
  (*it)->onlyCFoo();
}

//This part I am not sure about
cout << "Third loop:" << endl;
for (Iterate all 3 loops i.e. *it points to As, then Bs then Cs) {
  (*it)->foo();
}

Для вывода:

First loop:
I am B!
I am B!
I am B!

Second loop:
I am C!
I am C!
I am C!

Third loop:
I am A!
I am A!
I am A!
B pretending to be A.
B pretending to be A.
B pretending to be A.
C pretending to be A.
C pretending to be A.
C pretending to be A.

т.е. иногда я хочу повторять только объекты B, но иногда я хочу повторять все объекты.

Одним из решений было бы сохранить их все в списке, однако я хочу иметь возможность циклически проходить по ним в порядке типа, т. Е. Как затем B, а затем C.

Другим предлагаемым решением было использование итераторов или iterator_adapters, однако я никогда не использовал их раньше и не могу найти простой пример, чтобы помочь мне начать с ними.

Ответы [ 3 ]

1 голос
/ 23 мая 2010

Повышение адаптеров итераторов может дать вам то, что вам нужно - вы можете создать полиморфный список (все элементы), а затем создать адаптеры итераторов, которые выполняют итерацию только для элементов B или только для элементов C , Вы можете использовать стандартные итераторы для вывода списка всех элементов.

Как уже упоминалось, вам нужен полиморфный список, содержащий указатели, чтобы ваши элементы не разрезались. Затем вам необходимо управлять временем жизни элементов, т.е. обязательно удалять их при удалении контейнера. Существуют классы интеллектуальных указателей, которые могут упростить эту задачу.

0 голосов
/ 23 мая 2010

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

Не имеет значения, используете ли вы boost :: filter_iterator (один из специализированных адаптеров в boost), поскольку вам все еще нужно реализовать функцию предиката, чтобы решить, является ли этот объект тем, что вы ищете.

Возможно, вы захотите взглянуть на это: Поиск типа объекта в C ++ Я бы сказал, что это либо использование RTTI, либо добавление вашей собственной информации о типе в ваш класс.

0 голосов
/ 23 мая 2010

Если вы хотите иметь один список, вы можете перебрать, чтобы вызвать foo(), для всех объектов полиморфным способом (то есть, так что правильная версия foo() вызывается для каждого объекта), у вас естьсоздать список указателей на все Ваши объекты, хранящиеся в других контейнерах, и вызвать foo () с помощью этих указателей.Указатели должны быть типа A *.

Я предполагаю, что право собственности на Ваши объекты принадлежит этим другим контейнерам.

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