Шаг 16.
Ключевое слово __rtti и опция -RT

    На этом шаге мы закончим рассматривать динамическую идентификацию типов.

    По умолчанию в Borland C++ динамическое определение типов (RTTI) всегда разрешено. Однако его можно разрешать или запрещать, используя ключ -RT (подробнее смотри шаг 17). Если RTTI запрещено или аргументом typeid является указатель или ссылка на класс без виртуальных функций, typeid возвращает ссылку на объект const typeinfo, описывающий объявленный тип указателя или ссылки, но не реальный объект (т.е. указатель или ссылку на него).

    Если при компиляции использовать ключ -RT- (то есть отключить динамическое определение типов) и некоторый базовый класс объявлен __rtti, то все полиморфные базовые классы также должны быть объявлены как __rtti.

    struct __rtti  S1 { virtual s1(); }; // Полиморфизм.
    struct __rtti  S2 { virtual s2(); }; // Полиморфизм.
    struct X: S1, S2 {};

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

    Если компилировать указанные ниже строки с ключом -RT-, вы должны объявить X с модификатором __rtti. В противном случае изменение порядка следования базовых классов для X вызовет ошибку при компиляции:

    Can't inherit nоn RTTI class from RTTI base 'S1'
    (Невозможно наследовать не RTTI-класс из базового RTTI-класса 'S1').

   

    struct __rtti S1
      { virtual func(); };    // Полиморфный класс. 
    struct S2
      { };                        // Неполиморфный класс.
    struct __rtti X: S1, S2
      { };

    В данном случае класс X явно объявлен как __rtti. Это сделано как раз для того, чтобы не зависеть от порядка следования базовых классов при описании X.

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

    struct __rtti  S1   {   };   //  Неполиморфные классы.
    struct S2   {   } ;
    struct X: S2, S1 { }; // Порядок следования базовых классов несущественен.

    Обратите внимание на то, что применение __rtti или ключа -RT не преобразует статический класс в полиморфный класс.

//EXC16_1.СРР - динамическая идентификация типов для
//полиморфных классов.
#include  <iostream.h> 
#include  <typeinfo.h>
class __rtti Alpha
{ // Alpha и порожденные из него - RTTI-классы 
  virtual void func() {}; //  Виртуальная функция делает
};                        //  класс Alpha полиморфным.
class B :  public Alpha  {};  //В  - тоже RTTI. 
int main (void)
{ 
  B Binst; //Копия класса В.
  B *Bptr; // Указатель на класс В.
  Bptr = &Binst; // Инициализация указателя.
  try
  { // Какого типа  *Bptr?
    if (typeid(*Bptr) == typeid(B))
       cout << "Тип " << typeid(*Bptr).name() << "."; 
    if (typeid(*Bptr) != typeid(Alpha))
       cout << "\nУказатель не типа Alpha.";
    return 0; 
  } 
  catch (Bad_typeid)
  { 
    cout << "Ошибка функции typeid()."; 
    return 1;
  }
}
Текст этой программы можно взять здесь.

    Результат работы программы:

    Тип В.
    Указатель не типа Alpha.

    На следующем шаге мы рассмотрим опции компилятора, относящиеся к обработке исключений и динамическому определению типов.




Предыдущий шаг Содержание Следующий шаг