Страницы

Поиск по вопросам

пятница, 26 октября 2018 г.

Обход всех экземпляров всех наследников класса С++

Здравствуйте! Предположим есть некий класс
class Parent {
protected:
static Parent *Head_ptr; static Parent *Tail_ptr; Parent *NextObject_ptr;
virtual void SomeVirtualMethod(void){}
static void AllSomeVirtualMethods(void) { Parent *CurrentObject_ptr = Parent::Head_ptr;
while (CurrentObject_ptr != NULL) { CurrentObject_ptr->SomeVirtualMethod(); CurrentObject_ptr = CurrentObject_ptr->NextObject_ptr; } }
public:
Parent() { if (Parent::Head_ptr == NULL) { Parent::Head_ptr = this; } else { Tail_ptr->NextObject_ptr = this; this->NextObject_ptr = NULL; }
Parent::Tail_ptr = this; } };
Если создавать экземпляры класса Parent, то по задумке указатель на каждый добавленный объект записывается в предыдущем объекте. Таким образом, осуществляется вызов всех методов созданных объектов данного класса по сформированному списку.
Однако, задача усложняется. Мне необходимо перебирать все объекты каждого из унаследованных от Parent классов.
Фактически, мне нужен следующий порядок вызова виртуальных функций SomeVirtualMethod. По очереди вызываются виртуальные методы всех объектов первого унаследованного класса, далее по очереди вызываются виртуальные методы всех объектов второго унаследованного класса и так для всех унаследованных классов. Как лучше реализовать такой способ обхода?
Так же меня интересует в целом как обходить именно унаследованные классы а не их объекты. К примеру считать из каждого наследованного класса значение статической переменной унаследованной от базового класса.


Ответ

Могу предложить включить RTTI. После этого выполняем первичный перебор всех объектов и заносим их в std::multimap (то есть группируем указатели на объекты по общему фактическому типу дочернего класса; и да, цикл while можно переписать на for):
static void AllSomeVirtualMethods(void) { std::multimap perTypeGrouping; for( Parent *CurrentObject_ptr = Parent::Head_ptr; CurrentObject_ptr != NULL; CurrentObject_ptr = CurrentObject_ptr->NextObject_ptr ) { perTypeGrouping.insert( std::type_index(typeid(*CurrentObject_ptr)), CurrentObject_ptr ); } }
После этого мы проходим уже по multimap-у. Так как ассоциативный массив гарантирует упорядоченность по ключу, то все объекты одного фактического класса окажутся по соседству.
for( std::multimap::iterator entry = perTypeGrouping.begin(), entry != perTypeGrouping.end(); ++entry ) entry->second->SomeVirtualMethod();

Комментариев нет:

Отправить комментарий