В C ++ проверьте, являются ли два экземпляра базового класса одним и тем же подклассом - PullRequest
8 голосов
/ 05 октября 2010

Код ниже объясняет проблему. Заполните same_sub_class, чтобы обнаружить, если два указателя на виртуальный базовый класс A фактически являются одним и тем же конкретным класс.

struct A {
    ...
}:

struct B : public A {
    ...
}:

struct C : public A {
    ...
}


bool same_sub_class(A * a1, A * a2){
    // Fill this in to return true if a1 and a2 are
    // of the same concrete class
}

EDIT:

Когда я смотрю на свое приложение, мне нужно что-то немного отличное от приведенного выше. Мне нужно иметь возможность группировать экземпляры по их type_id.

FYI. У меня есть мини-система символьной алгебры, поэтому для выполнения манипуляций важно знать тип класса иногда для сортировки и перестановки выражений.

Итак, вектор указателей указывает, как сгруппировать их по их type_id. Мне нужно было бы иметь возможность хэшировать type_id или генерировать уникальное целое число для каждого класса.

Ответы [ 6 ]

18 голосов
/ 05 октября 2010

Если вы можете использовать RTTI,

typeid(*a1) == typeid(*a2)

Я думаю, вам также нужно

#include <typeinfo>

И у вас должна быть виртуальная функция в ваших классах, чтобы существовала виртуальная таблица:деструктор должен работать нормально.

ОБНОВЛЕНИЕ :

Я не уверен, что полностью понимаю, каковы ваши требования к группировке (Вам нужен какой-то детерминированный порядок?Что должно произойти с подклассами?), Но вы можете попробовать использовать значение , возвращаемое оператором typeid, либо:

  • Хешировать строку, возвращаемую из typeid(*ptr).name()
  • Используйте typeid(*a1).before(typeid(*a2)) в качестве критерия порядка.Это не имеет никакого детерминизма между пробегами, все же.

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

7 голосов
/ 05 октября 2010
typeid(*a1) == typeid(*a2)

Обратите внимание на разыменование, это важно.

2 голосов
/ 05 октября 2010

Вы можете сделать свой собственный идентификатор типа:

struct A{
...
protected:
 enum TypeTag{B_TYPE, C_TYPE};
 TypeTag typeTag;
};

А затем в конструкторах подклассов:

B::B()
: typeTag(TypeTag::B_TYPE)
{
...
}

C::C()
: typeTag(TypeTag::C_TYPE)
{
...
}
1 голос
/ 07 октября 2010

На самом деле есть довольно простые ответы на это.Но это требует постановки вопросов немного яснее.

(A) Если я хочу сохранить объекты typeinfo в unordered_set, что мне нужно сделать?

typeinfo поддерживает == и имя() метод.Имя можно использовать для генерации хеша и == для равенства

(B) Если я хочу сохранить объекты typeinfo в order_set (std :: set), что мне нужно сделать?

typeinfo поддерживает метод == и before ().Немного обернув эти два метода, я могу реализовать интерфейс для функции Compare, который дает мне строгий слабый порядок.

0 голосов
/ 05 октября 2010

Один прием, который может работать или не работать с RTTI, в зависимости от вашего компилятора, заключается в следующем:

const type_info &a1_type_info= typeid(*a1);
const type_info &a2_type_info= typeid(*a2);

return &a1_type_info==&a2_type_info || a1_type_info==a2_type_info;

Если ваш компилятор создает type_info экземпляров по значению, это не пройдёт первый тест, но завершится успешнона втором тесте.Если ваш компилятор кэширует экземпляры, первый тест будет успешным (если это тот же тип) и будет намного быстрее, так как это просто сравнение указателя.Если ваш компилятор возвращает разные экземпляры, поскольку a1 и a2 получены из разных общих библиотек, он все равно должен работать.

0 голосов
/ 05 октября 2010

В C ++ есть функция, называемая RTTI (информация о типе времени выполнения), которая позволяет вам делать такие вещи.

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

...