RTTI приводит к накладным расходам, так что компиляторы обычно по умолчанию его отключают. Скорее всего ваш компилятор имеет параметр командной строки для включения RTTI. Также это не единственный способ, которым можно получить информацию о типе. Другая методика приведена в рецепте 8.7.
Рецепт 8.7.
8.7. Определение, является ли класс объекта подклассом другого класса
Имеется два объекта и требуется узнать, имеют ли их классы отношения на уровне базовый класс/производный класс, или они не связаны друг с другом.
Используйте оператор dynamic_cast
#include
#include
using namespace std;
class Base {
public:
virtual ~Base() {} // Делаем класс полиморфным
};
class Derived : public Base {
public:
virtual ~Derived() {}
};
int main() {
Derived d;
// Запрашиваем тип отношений
if (dynamic_cast
cout << "Derived является классом, производным от Base" << endl;
} else {
cout << "Derived HE является классом, производным от Base" << endl;
}
}
Для запроса отношений между двумя типами используйте оператор dynamic_cast
dynamic_cast
принимает указатель или ссылку на некий тип и пытается преобразовать его к указателю или ссылке на производный класс, т.е. выполняя преобразование типа вниз по иерархии классов. Если есть Base*
, который указывает на объект Derived
, то dynamic_cast (&d)
возвращает указатель типа Derived
только в том случае, если d
— это объект типа, производного от Base
. Если преобразование невозможно (из-за того, что Derived
не является подклассом — явным или косвенным — класса Base
), то преобразование завершается неудачей и, если в dynamic_cast
был передан указатель на производный класс, возвращается NULL
. Если в него была передана ссылка, то выбрасывается стандартное исключение bad_cast
. Также базовый класс должен наследоваться как public
и это наследование не должно быть двусмысленным. Результат говорит о том, является ли один класс наследником другого класса. Вот что я сделал в примере 8.7.if (dynamic_cast
Здесь возвращается нe-NULL
d
— это объект класса, производного от Base
. Эту возможность можно использовать для определения отношения любых двух классов. Единственным требованием является то, что аргумент объекта должен быть Если этот синтаксис кажется вам слишком запутанным, используйте макрос, скрывающий некоторые подробности.
#define IS_DERIVED_FROM(BaseClass, x) (dynamic_cast
//...
if (IS_DERIVED_FROM(Base, l)){//...
Но помните, что такая информация о типах не бесплатна, так как dynamic_cast
Рецепт 8.6.
8.8. Присвоение каждому экземпляру класса уникального идентификатора
Требуется, чтобы каждый объект класса имел уникальный идентификатор.
Для отслеживания следующего доступного для использования идентификатора используйте статическую переменную-член. В конструкторе присвойте текущему объекту очередное доступное значение, а затем инкрементируйте статическую переменную. Чтобы понять, как это работает, посмотрите на пример 8.8.
#include
class UniqueID {
protected:
static int nextID;
public:
int id;
UniqueID();
UniqueID(const UniqueID& orig);
UniqueID& operator=(const UniqueID& orig);
};