zeby RTTI dzialalo, obiekt musi miec vtable i kropka. stad wymog aby byla jakas metoda wirtualna. jesli masz wspolna baze - BASE_NODE - umiesc w niej jakakolwiek durna metode wirtualna, moze byc nawet niepotrzebna - zostanie ona odziedziczona przez wzystkie pochodne i wszystkie pochodne z automatu beda mialy vtable. np. destruktor:
class BASE_NODE
{public:
virtual ~BASE_NODE() {..a tutaj kod destruktora lub pustka..}
};
class NODE: public BASE_NODE //z automatu ~NODE jest wirtualne, wiec jest vtable, wiec NODE jest RTTI-ok
{
};
hm.. lepsze..? ogolnie z RTTI chyba przekombinowales.. po co rozszcepiac node'y na dwie klasy? chyba ze to ma jakis wyzszy sens.. IMHO, jedna klasa NODE calkowicie wystarczy takze do zaimplementowania liscia.
Tradycyjnie na chlopaski rozum: w NODE umieszczasz trzy wskanziki/wartosci: lewe, prawe, wartosc. Jak to jest node, to wartosc jest pusta, ale wskazniki na dzieci - ustawione. Jak to jest lisc - wartosc jest niepusta a wskazniki sa nullami. Mozna sie sprzeczac czy to bedzie wydajniejsze pamieciowo niz RTTI.
Wiec, mozna zajetosc pamieci zmniejszyc o 1/3: biorac pod uwage ze w drzewie binarnym dla kazdego wezla zachodzi ze albo LEWE==PRAWE==NULL i jest to lisc, albo LEWE!=PRAWE i jest to wezel.. to mozna zauwazyc ze tak na prawde warunkiem liscia mozna uczynic LEWE==PRAWE i zrobic taki trick:
struct Wartosc; //costam, nieistotne co
class Node
{
union {Node* lewy; Wartosc* w1; }; //to zajmuje miejsce jednego wskaznika
union {Node* prawy; Wartosc* w2; }; //i to rowniez
public:
Node(Wartosc* ptr) : //inicjalizujac jako LEAF, upewniamy sie ze L i R sa ROWNE
w1(ptr),
w2(ptr)
{ ;
}
Node(Node* left, Node* right) : //inicjalizujac jako NODE - wrecz przeciwnie
lewy(left),
prawy(right)
{ if(lewy==prawy) throw logic_error("dzieci musza byc rozne");
}
bool IsLeaf() //teraz, uzywajac tych zalozen..
{ return lewy == prawy; //nie wazne czy sa rowne NULL czy COS, wazne ze rowne
}
Wartosc* getValue()
{ if(!IsLeaf())throw logic_error("to nie lisc!");
return w1; //nie wazne czy w1 czy w2 - przeciez sa rowne
}
void setValue(Wartosc* ptr)
{ if(!IsLeaf())throw logic_error("to nie lisc!");
w1=w2=ptr;
}
}
w ten sposob mamy jedynie NODE'y i nauczylismy NODE'y trzymac wartosci ...bez straty miejsca na trzeci wskaznik.
zmiast unionow mozna by sobie castowac static_castem z NODE* na WARTOSC*, ale uniony chyba jednak ladniejsze.. i oczywiscie typ WARTOSC jest nie istotny, wazne zeby to byl wskaznik, albo cos niewiekszego niz sizeof(void*)