Итерировать по всем объектам класса (но не по родителям этого класса - C ++) - PullRequest
0 голосов
/ 17 ноября 2010

Я хочу создать структуру, в которой я могу «перебирать» все объекты класса (и, возможно, объекты всех производных классов, хотя тогда это игнорируется).Однако он не должен перебирать родительские классы:

Предположим, у меня есть следующая система:

A - это базовый класс
C и D получены из того, что
E получено из C

Теперь, еслиЯ бы «перебрал D», я хотел бы перебрать D, но не «а».Однако в то же самое время я хотел бы иметь возможность «перебирать все по C» - это позволило бы мне перебрать все объекты «C» - и, возможно, также все объекты E (хотя в этом нет необходимости, это тоже неплохо).

Как я могу это сделать?

Я попытался поместить статическую переменную myObjects, которая связывала бы все объекты. Однако вскоре я заметил, что не могу перегрузить статические переменные.в производных классах.(и, следовательно, «myObjects» в C будет таким же, как «myObjects» в A или D)

Ответы [ 4 ]

2 голосов
/ 17 ноября 2010
int count = std::accumulate(x.begin(), x.end(), 0, [](int current_count, A* a)
                           {
                             if (dynamic_cast<D*>(a)) ++current_count;
                             return current_count;
                           });

должен сделать трюк.

Если у вас нет доступной лямбды, конечно, вам придется использовать все это в реальной функции.

count_if версия:

auto count = std::count_if(x.begin(), x.end(), [](A* a) { return dynamic_cast<D*>(a) != 0; });

Если у вас нет авто, вам нужно объявить тип: std::iterator_traits<X_type::iterator>::difference_type

Вы можете просто попробовать присвоить int, но, если я правильно читаю, difference_type может быть любым целым типом и может вызвать предупреждение / переполнение. Сомнительно, что это произойдет, и static_cast исправит это.

Если вы просто хотите вызвать некоторые операторы D *, используйте для этого foreach и приведенную выше методологию. Возможно, вы захотите просмотреть различные шаблоны посетителей.

0 голосов
/ 17 ноября 2010

Сделать абстрактного класса-посредника между A и его детьми. Поместите туда свой статический объект. Затем выведите классы из этого, а не непосредственно из А. Например:

class A {};


 // make this class abstract, or not
class subA : A {
    static std::list<subA *> list_;
};

class C : subA {};
class D : subA {};
0 голосов
/ 17 ноября 2010

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

Затем при построении каждый класс предоставляет конструктор protected для использованияподклассы и конструктор public для создания не наследуемого экземпляра.Конструктор protected в каждом классе не добавляет this к контейнеру экземпляров, а конструктор public добавляет this к контейнеру.

Таким образом, статический контейнер в каждом классе содержит толькоте экземпляры класса, которые не имеют подклассов.Виртуальная функция в базовом классе для доступа к списку экземпляров может быть переопределена в каждом подклассе для доступа к контейнеру, специфичному для класса.

Конструкция уничтожения и копирования должна быть достаточно умной, чтобы правильно поддерживать контейнер.

0 голосов
/ 17 ноября 2010

Однако вскоре я заметил, что не могу перегрузить статические переменные в производных классах

Конечно, нет, вы не можете перегружать переменные. Перегрузка относится только к функциям, поскольку они могут различаться по сигнатурам.

Вы могли бы иметь конструктор, принимающий bool в базовом классе, который указывает, должен ли объект быть помещен в «список известных объектов» и предоставляет false по умолчанию. Затем вызывайте только тот конструктор с true внутри производного класса, чьи объекты фактически должны быть вставлены в список.

Но, вероятно, есть даже лучшее решение, которое исключает наследование в пользу политик.

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