Неявное приведение указателя на объект производного типа к указателю на объект базового типа компилятор прекрасно выполняет сам, так как производный класс содержит полные определения своих базовых классов => такое повышающее (upcast) приведение типа всегда безопасно!
B b;
A* pA = &b;
Верно и следующее утверждение: если объект на самом деле является объектом производного типа, а в нашем распоряжении имеется указатель на базовый класс, то корректным должно являться и преобразование указателя “вниз” по иерархии классов вплоть до преобразования такого указателя к указателю на фактический (целевой) тип – понижающее приведение (downcast).
Для приведения указателя на базовый тип к указателю производного типа предназначен оператор явного приведения типа static_cast – это механизм времени компиляции!
//A и B связаны наследованием
class A{
};
class B:public A{
};
// С – «автономный» класс
class С{
};
void F(A* pA)
{
B* pB = static_cast<B*>(pA);//с точки зрения компилятора все корректно, так как классы связаны наследованием!
}
void main()
{
B b;
F(&b);//компилятор преобразует адрес B* к A* - это всегда корректно
//Но!
D d;
// F(&d); //ошибка компилятора – такого преобразования нет!
//Но!
A a;
F(&a); //ошибки компилятора нет, но результат некорректный, так как на самом деле объект A, а не B!
}
Замечание: компилятор проверяет только тот факт, что оба класса связаны с помощью наследования => считает такое приведение корректным. А на самом деле такое преобразование небезопасно! Поэтому возникла необходимость в способе проверки возможности такого преобразования.
Замечание: static_cast обычно используется для неполиморфных типов (нет виртуальных функций).
Замечание: хотя мы будем обсуждать RTTI применительно к указателям, те же аспекты применимы и к ссылкам.
RTTI характеризуется тремя понятиями:
1) оператор dynamic_cast – для преобразования полиморфных типов
2) оператор typeid – для определения точного (exact) типа объекта
3) класс type_info – (это то, что возвращает оператор typeid)
1) в опциях проекта Project\Properties\C/C++\Language – включить Enable Run-Time Type info (или /GR)
2) #include <typeinfo>
3) механизм работает только для полиморфных классов (то есть задействованы таблицы виртуальных функций)
Идентификация типов во время выполнения позволяет получить информацию об объектах и классах. При этом для хранения запрашиваемой информации должна быть отведена область памяти.
Логично:
1) сколько бы объектов класса X мы не создавали, достаточно хранить информацию собственно о типе X в единственном экземпляре в каждом классе => для каждого класса компилятор создает структуру данных типа type_info
2) должен существовать способ получения этой информации для каждого объекта => доступ к объекту type_info можно получить при помощи оператора typeid.
3) Что существует в единственном экземпляре для всех объектов? – static или таблица виртуальных функций. В спецификации языка сказано, что получение этой информации гарантируется только для полиморфных типов (то есть если есть хотя бы одна виртуальная функция). Данные RTTI выполняют примерно ту же задачу, что и таблица виртуальных функций => RTTI была разработана именно с помощью виртуальной таблицы класса. Например индекс 0 в таблице может содержать указатель на объект type_info:
При такой реализации память будет тратиться только на добавление еще одной ячейки в каждую таблицу виртуальных функций + выделение памяти для хранения объекта type_info для каждого класса.
class type_info {
public:
virtual ~type_info();
int operator==(const type_info& rhs) const;
int operator!=(const type_info& rhs) const;
int before(const type_info& rhs) const;
const char* name() const; //имя, котороедалпрограммист (human-readable)
const char* raw_name() const; //декорированноеимя
private:
...
};
Основные возможности: 1) перегружены операторы == и !=.
2) + методы для получения имени класса.
const type_info& typeid(объект) //где в качестве объекта может выступать выражение, например (*P)
const type_info& typeid(тип)
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.