Выполнение с помощью операции dynamic_cast повышающего преобразования
равносильно простому присваиванию:
class В{ / * ... * / };
class С: public В{ /* ... */ };
С* с = new С;
В* b = dynamic_cast<B*>(c); // Эквивалентно В* b = с;
29.3. Перекрёстное преобразование
Операция dynamic_cast позволяет выполнять безопасное преобразование типа между производными классами одного базового класса, например:
#include <iostream.h>
#include <typeinfo.h>
class B{
public: virtual void fl ( ) { };
};
class C: public B{
public: void f2(){ ... };
};
class D: public B{ ... };
void demo(D* p){
C* с = dynamic_cast<C*>(p);
if(c)c->f2();
else cout « " не выполнено ";
}
int main(){
B* b = new C: demo((D*)b);
return 0:
}
Классы С и D являются производными от класса В. Функции demo передается указатель на класс D, являющийся на самом деле указателем на «братский» для него класс С, поэтому динамическое преобразование типа из D в С в функции demo завершается успешно.
При необходимости можно осуществить преобразование между базовыми классами
одного производного класса, например:
#include <iostream.h>
finclude <typeinfo.h>
class B{
public: virtual void fl ( ) { . . . } ; / / В С
}: // \ /
class C{ // D
public: virtual void f2(){ ... };
};
class D: public B, public C{};
void demo(B* b){
С* с = dynamic_cast<C*>(b);
if(c)c->f2();
}
int main(){
D* d = new D; demo(d);
Return 0;
}
Класс D является потомком В и С, поэтому содержит методы обоих классов. Если в функцию demo передается на самом деле указатель не на В, а на D, его можно преобразовать к его второму базовому классу С.
ВНИМАНИЕ!!! Также смотреть static_cast!
Преобразование ссылок
Для аргумента-ссылки смысл операции преобразования несколько иной, чем для
указателя. Поскольку ссылка всегда указывает на конкретный объект, операция dynamic_cast должна выполнять преобразование именно к типу этого объекта. Корректность приведения проверяется автоматически, в случае несовпадения порождается исключение bad_cast:
#include <iostream.h>
#include <typeinfo.h>
class B{
public: virtual void fl ( ) { };
};
class C: public B{
public: void f2(){ ... };
};
void demo(B& p){
try{
C& с = dynamic_cast<C&>(p);
C.f2();
catch(bad_cast){
}
}
int main(){
B* b = new B; demo(*b); // Порождается исключение
С* с = new С; demo(*c); // Правильно
Return 0;
}
Приведение типа указателя
ВНИМАНИЕ!!! Смотреть reinterpret_cast!
НАСЛЕДОВАНИЕ
Определение наследования. Примеры иерархии понятий.
Наследование позволяет создавать иерархию (сложную древовидную структуру) объектов, начиная с некоторого первоначального, и кончая преемственными классами, имеющие часть признаков от предыдущего. Все классы порождены от единственного родителя класса Object.
Механизм наследования классов позволяет строить иерархии, в которых производные
классы получают элементы родительских, или базовых, классов и могут дополнять их или изменять их свойства. При большом количестве никак не связанных классов управлять ими становится невозможным. Наследование позволяет справиться с этой проблемой путем упорядочивания и ранжирования классов,
то есть объединения общих для нескольких классов свойств в одном классе и использования его в качестве базового. Классы, находящиеся ближе к началу иерархии, объединяют в себе наиболее общие черты для всех нижележащих классов. По мере продвижения вниз по иерархии
классы приобретают все больше конкретных черт. Множественное наследование позволяет одному классу обладать свойствами двух и более родительских классов.
Реализация наследования в ООП.
Производный класс имеет все поля и методы предка + добавочные методы (поля, изменённые права доступа к элементам предка).
Класс – предок – базовый (порождающий, родительский);
класс – наследник – производный (порождённый, класс-потомок, наследник, дочерний класс);
Непосредственный базовый класс входит в список базовых классов при определении класса.
30.3.Возможности наследования классов:
Можно:
Добавлять в производный класс поля и методы; модифицировать в производном классе методы базового класса;
Нельзя: