Можно ли с помощь полиморфизма реализовать разное содержание объекта?
Я хочу написать дерево со строго заданной глубиной, чтоб поле data находилось только на самом нижнем уровне дерево. Иными словами, я хочу реализовать две структуры ноды дерева, первая будет содержать только указатели на потомков, вторая, которая будет содержать указатели на потомков и поле data. Ниже пример.
struct Node1{
Node1* left;
Node1* right;
}
struct Node2{
Node2* left;
Node2* right;
T data;
}
Можно ли добиться этого с помощью полиморфизма, если наследовать Node2 от Node1, то при создании Node2 через указатель на Node1 невозможно получить доступ к полю data, т.к поле data не содержится в Node1.
Ответы (1 шт):
В плюсах обычно делаются классами с виртуализацией.
class Node1 {
public :
Node1* left;
Node1* right;
virtual bool hasData(){return false;}
};
class Node2 : public Node1 {
public :
T data ;
virtual bool hasData(){return true;}
} ;
И если hasData() вернул true , то делаете static_cast<Node2*>(p)->data чтобы достать данные.
Без виртуальных функций и наследования такое делается по другому :
struct Node1 {
Node1* left;
Node1* right;
Node2 * son ;
} ;
struct Node2{
Node1 base ;
T data;
} ;
В данном примере Node2 - это наследник структуры Node1. Но чтобы добиться, что узел Node1 - это часть наследника Node2 придётся добавить ссылку на наследника. То есть сделать своими руками полиморфизм.
При конструкции простого узла создаётся структура Node1 с переменной son равным nullptr. А при создании Node2 в поле Node2.base.son = адрес данной структуры Node2;
Node2 n2 ;
n2 . base . son = & n2 ;
Создаёте дерево с узлами Node1 и проверяете son. Если son - не nullptr то это наследник Node2 и берёте данные .son->data.
Рабочий пример :
// g++ -std=c++11 -Wall -Wextra -Wpedantic poli.cpp -o poli && ./poli
# include <iostream>
class Node1 {
public :
Node1* left;
Node1* right;
virtual bool hasData(){return false;}
};
template <class T>
class Node2 : public Node1 {
public :
T data ;
virtual bool hasData(){return true;}
} ;
template<class T>
struct sNode2;
template<class T>
struct sNode1 {
sNode1<T>* left;
sNode1<T>* right;
sNode2<T> * son { nullptr } ;
sNode1(){}
sNode1(sNode2<T> * s):son{s}{}
} ;
template<class T>
struct sNode2{
sNode1<T> base { this } ;
T data;
} ;
int main(){
Node1 n1;
Node1 * p1 = & n1 ;
if(p1->hasData()) {
std::cout<<"Yes p1->hasData()"<<std::endl;
std::cout<<"data = "<<static_cast< Node2<int> * >( p1)->data<<std::endl; }
else
std::cout<<"No p1->hasData()"<<std::endl;
Node2<int> n2;
n2.data = 777 ;
Node1 * p2 = & n2 ;
if(p2->hasData()){
std::cout<<"Yes p2->hasData()"<<std::endl;
std::cout<<"data = "<<static_cast< Node2<int> * >( p2)->data<<std::endl; }
else
std::cout<<"No p2->hasData()"<<std::endl;
sNode1<int> sn1;
sNode1<int> * psn1 = & sn1;
if(psn1->son){
std::cout<<"Yes psn1.son"<<std::endl;
std::cout<<"data = "<<psn1->son->data<<std::endl;}
else
std::cout<<"No psn1.son"<<std::endl;
sNode2<int> sn2;
sn2.data = 666 ;
sNode1<int> * psn2 = & sn2.base;
if(psn2->son){
std::cout<<"Yes psn2.son"<<std::endl;
std::cout<<"data = "<<psn2->son->data<<std::endl;}
else
std::cout<<"No psn2.son"<<std::endl;
}
Вывод :
$ g++ -std=c++11 -Wall -Wextra -Wpedantic poli.cpp -o poli && ./poli
No p1->hasData()
Yes p2->hasData()
data = 777
No psn1.son
Yes psn2.son
data = 666