Язык программирования C++ для профессионалов



           

Класс Type_info - часть 2


class base_iterator { short i; short alloc; const Type_info* b; public: const Type_info* operator() (); void reset() { i = 0; }

base_iterator(const Type_info* bb, int direct=0); ~base_iterator() { if (alloc) delete[] (Type_info*)b; } };

В следующем примере используется необязательный параметр для указания, следует ли рассматривать все базовые классы (direct==0) или только прямые базовые классы (direct==1).

base_iterator::base_iterator(const Type_info* bb, int direct) { i = 0;

if (direct) { // использование списка прямых базовых классов b = bb; alloc = 0; return; }

// создание списка прямых базовых классов:

// int n = число базовых b = new const Type_info*[n+1]; // занести базовые классы в b

alloc = 1; return; }

const Type_info* base_iterator::operator() () { const Type_info* p = &b[i]; if (p) i++; return p; }

Теперь можно задать операции запросов о типе с помощью макроопределений:

#define static_type_info(T) T::info()

#define ptr_type_info(p) ((p)->get_info()) #define ref_type_info(r) ((r).get_info())

#define ptr_cast(T,p) \ (T::info()->can_cast((p)->get_info()) ? (T*)(p) : 0) #define ref_cast(T,r) \ (T::info()->can_cast((r).get_info()) \ ? 0 : throw Bad_cast(T::info()->name()), (T&)(r))

Предполагается, что тип особой ситуации Bad_cast (Ошибка_приведения) описан так:

class Bad_cast { const char* tn; // ... public: Bad_cast(const char* p) : tn(p) { } const char* cast_to() { return tn; } // ... };

В разделе §4.7 было сказано, что появление макроопределений служит сигналом возникших проблем. Здесь проблема в том, что только транслятор имеет непосредственный доступ к литеральным типам, а макроопределения скрывают специфику реализации. По сути для хранения информации для динамических запросов о типах предназначена таблица виртуальных функций. Если реализация непосредственно поддерживает динамическую идентификацию типа, то рассматриваемые операции можно реализовать более естественно, эффективно и элегантно. В частности, очень просто реализовать функцию ptr_cast(), которая преобразует указатель на виртуальный базовый класс в указатель на его производные классы.




Содержание  Назад  Вперед