Рекурсивно проверить суперкласс type_info

Есть ли способ проверить, что такое type_info суперкласса? В моей системе объекты идентифицируются набором битов. Который идентифицируется хэш-кодом type_info. Я хотел бы, чтобы некоторые из этих типов включали полиморфизм в том смысле, что моя система считает, что они находятся под одним и тем же битом. type_info создает уникальный хэш-код для каждого типа класса. Вместо этого я хочу, чтобы производные классы брали битовый набор своего суперкласса следующим образом:

Component > ISomeInterfaceComponent -> bit = 00001
              |
               \ ComponentContextA  -> bit = ISomeInterFaceComponent bit
              |
              \  ComponentContextB  -> bit = ISomeInterFaceComponent bit
              |
              \  ComponentContextC  -> bit = ISomeInterFaceComponent bit

Это должно добавить объект, содержащий компоненты, в одну систему для обработки.

На данный момент происходит вот что:

Component > ISomeInterFaceComponent -> bit = 00001
              |
               \ ComponentContextA  -> bit = 00010
              |
              \  ComponentContextB  -> bit = 00100
              |
              \  ComponentContextC  -> bit = 01000

Что требует, чтобы я создавал разные системы для всех компонентов.

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

Редактировать: Чтобы избежать путаницы, чтобы установить бит для типа, это выглядит следующим образом: ComponentTypeManager::getBit();

Поэтому я не работаю с экземплярами. И я хотел бы сохранить текущую систему в замке.


person Sidar    schedule 27.07.2012    source источник
comment
Связанный ответ на сумасшедший взлом Я написал, могу ли я сделать это только с помощью type_info?   -  person Flexo    schedule 28.07.2012
comment
С++ 11 предоставляет шаблон is_base_of, чтобы сделать то же самое. Но создавать десятки if/else в моей ситуации нецелесообразно. Я действительно думаю, что мне нужно как-то переделать это.   -  person Sidar    schedule 28.07.2012


Ответы (2)


Я не знаю никакого автоматического способа. Однако, если я вас понимаю, это можно сделать с небольшими дополнительными усилиями.

Для каждого из ваших «базовых» классов добавьте определение типа, которое ссылается на себя, и используйте его вместо этого в typeid(). Обратите внимание, что подклассы могут переопределить его. Если они это сделают, то получат свой собственный идентификатор, и их дети будут использовать его значение.

Обратите внимание, что другое решение, если вы вообще не хотите использовать typeid(), состоит в том, чтобы иметь статический член (или функцию-член) в базовых классах, который возвращает правильное значение для базы, а затем вызывать это непосредственно в вашем getBit() функция.

#include <iostream>
#include <iomanip>
#include <typeinfo>

struct Base1 
{
   typedef Base1 Base;

};

struct Base2
{
   typedef Base2 Base;
};

struct Derived1A : public Base1 { };   
struct Derived1B : public Base1 { };    
struct Derived2A : public Base2 { };    
struct Derived2B : public Base2 { };

template <typename T>
std::size_t getBit()
{
   // Do whatever you normally do here, but use T::Base instead of T
   return std::hash<std::string>()(typeid(typename T::Base).name());
}

int main()
{ 
   std::cout << std::boolalpha << getBit<Derived1A>() << " == " << getBit<Derived1B>() << " " << (getBit<Derived1A>() == getBit<Derived1B>()) << "\n";

   std::cout << std::boolalpha << getBit<Derived2A>() << " == " << getBit<Derived2B>() << " " <<(getBit<Derived2A>() == getBit<Derived2B>()) << "\n";

}

http://ideone.com/6ad08

person Dave S    schedule 27.07.2012
comment
Спасибо за ответ. Но я не вижу, чтобы это работало, поскольку все происходит от класса Component, который обеспечивает полиморфизм на базовом уровне. Думаю, надо как-то переделывать. - person Sidar; 28.07.2012
comment
@Sidar: Ну, это все еще должно работать. Ничто не мешает Base1 и Base2 иметь общий супертип. - person Dave S; 28.07.2012

Почему бы просто не создать переменную в базовом классе ISomeInterFaceComponent, которая не будет изменяться никакими производными классами (если только вы этого не хотите). Не похоже, что вам нужен полиморфизм, поскольку вы хотите, чтобы битовое значение было одинаковым независимо от типа производного класса, а не менялось в зависимости от типа. Если в будущем вам потребуется переопределить if для определенного производного типа, вы все равно можете сделать это специально для этого класса.

В качестве альтернативы вы можете использовать виртуальную функцию в базовом классе, которая возвращает int (значение бита - или любой другой тип, которым он на самом деле является), и просто не переопределять его в производных классах, которые вы хотите иметь то же значение бита, что и база.

Например

 class ISomeInterFaceComponent {
      virtual int GetBit() { return 1;};  // return bit value
 };


 class ComponentContextA : public ISomeInterFaceComponent {
      // Do not override GetBit() - let the base class function get called.
 };
person mathematician1975    schedule 27.07.2012
comment
Потому что типы определяются их фактическими именами классов, а не экземплярами. Получение битового типа происходит следующим образом: ComponentTypeManager::getBit‹ComponentA›(); В этом случае я не работаю с экземплярами. Я непосредственно работаю с самим классом. - person Sidar; 28.07.2012
comment
@Сидар - понятно. В таком случае я не знаю. Прости. - person mathematician1975; 28.07.2012