C++ Программирование в среде С++ Builder 5

         

Type info


Класс type_info объявлен следующим образом:

class _TIDIST _rtti type_info {

public:

tpid * tpp;

private:

cdecl type_info(const type info FAR &);

type info & cdecl operator=(const type_info _FAR &);

public:

virtual _cdecl ~type_info() ;

bool cdecl operator==(const type info FAR &) const;

bool cdecl operator!=(const type info FAR &) const;

bool _cdecl before(const type_info _FAR &) const;

const char _FAR *_cdecl name() const;

protected:

cdecl type_info(tpid * tpp) { tpp = tpp; } };



Ключевое слово _rtti перед именем класса гарантирует, что информация о типе для него будет генерироваться вне зависимости от состояния флажка Enable RTTI на странице C++ диалога Project Options (ему соответствует ключ компилятора -rt).

Открытые элементы класса представлены операциями сравнения на равенство и неравенство, а также функциями name () и before (). Первая возвращает указатель на символьную строку с именем типа. Вторая возвращает true, если класс ее объекта является базовым по отношению к классу аргумента.

Вот пример с использованием операции typeid и класса type_info:

Листинг 13.1. Операция typeid

//////////////////////////////////////////////////////

// Typeinfo.срр: Операция typeid.

//

#include <typeinfo.h>

#include <iostream.h>

#include <string.h>

#pragma hdrstop

#include <condefs.h>

class Base { // Базовый класс.

public:

virtual ~Base (){} };

class Derived: public Base { // Производный класс.

char *str;

public:

Derived(const char *s) {

str = new char[strien(s)+1];

strcpy(str, s);

}

~Derived() { delete [] str;}

const char *Get() ( return str;}};

int main() {

Derived d("Derived class' string.");

Base &bRef = d; // Базовая ссылка на производный объект.

cout << "Typeinfo of bRef: " << typeid(bRef).name() << end1;

if (typeid(bRef) == typeid(Derived))

cout << "Contents of bRef: "<< ((Derived 6)bRef).Get() << endl;

else

cout << "Cannot cast safely bRef to Derived." << endl;


return 0;

Здесь демонстрируется операция typeid, сравнение типов и функция name () класса type_inf о. Программа выводит:

Typeinfo of bRef: Derived

Contents of bRef: Derived class' string.

Сравнение типов объекта bRef и Derived показывает, что они совпадают, и программа приводит ссылку к производному типу. Если закомментировать виртуальный деструктор класса Base, он станет неполиморфным, и typeid уже не сможет определить тип объекта, на который в действительности ссылается bRef:

Typeinfo of bRef: Base

Cannot cast safely bRef to Derived.



Эта программа является примером того, как не следует поступать. Идентифицировать класс, затем привести ссылку к нужному типу — это попытка поставить RTTI на место виртуального механизма. Гораздо проще сделать функцию Get() виртуальной:

class Base { public:

virtual ~Base () { }

virtual const char *Get() { throw MyExcpt; } };

try {

cout << "Contents of bRef: " << bRef.Get() << endl;

} catch(MyExcept) {

}

При недопустимом типе объекта выбрасывается исключение (возможны и другие решения).

RTTI следует применять только в тех случаях, когда тип объекта не известен во время компиляции и нецелесообразно применение других средств C++ вроде позднего связывания.


Содержание раздела