Когда на практике полезно использовать dynamic_cast от родителя к потомку? Всегда ли это плохая практика?
Это НЕ дубликат: Полиморфизм C ++: от родительского класса к дочернему Информация о типах времени выполнения в C ++
Сначала давайте начнем с примера кода, а затем сделаем некоторые выводы.
#include<iostream>
using namespace std;
class B { public: virtual void fun() {cout<<"!class B!\n";} };
class D: public B { public: void fun() {cout<<"!class D!\n";} };
int main()
{
///////// 1. Dynamic initialization parent from child
B *bAux = new D;
D *d = dynamic_cast<D*>(bAux);
cout<<"1.1. for d is "; d->fun(); //class D
B *b = dynamic_cast<B*>(d);
cout<<"1.2. for b is "; b->fun(); //class D
///////// 2. Dynamic initialization child from parent
//D *dAux4 = new B; //invalid conversion from ‘B*’ to ‘D*’
///////// 3. Casting the parent to child
B *bAux2 = new B;
cout<<"3.1. for bAux2 is "; bAux2->fun(); //class B
D *d2 = dynamic_cast<D*>(bAux2);
if (d2 != NULL){ cout<<"3.2. for d2 is "; d2->fun(); } //cannot cast parent to child
else cout<<"3.2. cannot cast B* to D* \n";
///////// 4. Casting the child to parent
D *dAux3 = new D;
cout<<"4.1. for dAux3 is "; dAux3->fun(); //class D
B *b3 = dynamic_cast<B*>(dAux3);
cout<<"4.2. for b3 is "; b3->fun(); //class D
getchar();
return 0;
}
Во-вторых, подведем итоги. Результат:
1.1. for d is !class D!
1.2. for b is !class D!
3.1. for bAux2 is !class B!
3.2. cannot cast B* to D*
4.1. for dAux3 is !class D!
4.2. for b3 is !class D!
Но для случая 3 мы фактически пытаемся выполнить динамическое приведение из B * в D * (как уже упоминалось, это невозможно). Интересно, в каких случаях это полезно? Вы можете нарушить приведение типов (в качестве параллели, в случае проверки статического типа, возникает хорошо известная проблема: поскольку медведь - это животное, не должен ли набор медведей быть набором животных? Нет, потому что затем можно вставить Волка в набор и получить Волка среди Медведей).
Итак, вопрос в том, в каком случае полезно динамическое преобразование от родителя к потомку? Это плохая практика?
РЕДАКТИРОВАТЬ: после обсуждения конкретный случай:
///////// 5. Try to cast the parent initialized from a child to another child
B *bAux = new D;
F *f = dynamic_cast<F*>(bAux);
if(f == NULL)
cout<<"5.1. Cannot cast the parent initialized from a child to another child \n";// f->fun(); //segmentation fault
B *b = dynamic_cast<B*>(f);
if(b == NULL)
cout<<"5.2. Cannot cast the NULL pointer back to parent \n"; //b->fun(); //segmentation fault