class Dog; class Human; class Dog { Human* link; public: Dog(): link(NULL) {} void SetLink(Human* l) { link = l; } const Human* GetLink() const { return link; } } class Human { Dog* link; public: Human(): link(NULL) {} void SetLink(Dog* l) { link = l; } const Dog* GetLink() const { return link; } }
Human *h = new Human(); Dog *d = new Dog(); h->SetLink(d); d->SetLink(h);
d->SetLink(h)
.d->SetLink(h2)
. class Dog; class Human; class Dog { Human* link; public: Dog(): link(NULL) {} ~Dog() { if (link) link->SetLink(NULL); } void SetLink(Human* l) { if (link == l) return; Human* oldlink = link; link = NULL; if (oldlink) oldlink->SetLink(NULL); link = l; if (link) link->SetLink(this); } const Human* GetLink() const { return link; } } class Human { Dog* link; public: Human(): link(NULL) {} ~Human() { if (link) link->SetLink(NULL); } void SetLink(Dog* l) { if (link == l) return; Dog* oldlink = link; link = NULL; if (oldlink) oldlink->SetLink(NULL); link = l; if (link) link->SetLink(this); } const Dog* GetLink() const { return link; } }
SetLink()
methods became more complicated. Now, when setting the link in one direction, the method automatically sets the link in the other direction. Forget to install one of the links is impossible. Exactly as it is impossible to establish an incorrect back link: Human *h1, *h2; h1 = new Human(); h2 = new Human(); Dog *d = new Dog(); h1->SetLink(d); assert(h1->GetLink()->GetLink() == h1); //passed (d h1) d->SetLink(h2); assert(d->GetLink()->GetLink() == d); //passed (h2 d) assert(h1->GetLink() == NULL); //passed (h1 d)
GetLink()
you can always expect either a valid pointer or NULL. template<class M, class L> class O { L* link; public: O(): link(NULL) {} ~O() { if (link) link->SetLink(NULL); } void SetLink(L* l) { if (link == l) return; L* oldlink = link; link = NULL; if (oldlink) oldlink->SetLink(NULL); link = l; if (link) link->SetLink(static_cast<M*>(this)); } const L* GetLink() const { return link; } };
class Human; class Dog; class Human: public O<Human, Dog> {}; class Dog: public O<Dog, Human> {}; Human* h = new Human(); Dog* d = new Dog(); h->SetLink(d);
template<class M, class L> class O { ... }; class Human; class Dog; class Human: public O<Human, Dog> {}; class Dog {};
template<class M, class L> class O { ... }; class Human: public O<Human, Human> {}; Human *h1, *h2; ... h1->SetLink(h2);
SetLink()
method SetLink()
. template<class M, class L> class O { L* link; public: O(): link(NULL) {} ~O() { if (link) link->O<L,M>::SetLink(NULL); } void SetLink(L* l) { if (link == l) return; L* oldlink = link; link = NULL; if (oldlink) oldlink->O<L,M>::SetLink(NULL); link = l; if (link) link->O<L,M>::SetLink(static_cast<M*>(this)); } const L* GetLink() const { return link; } }; class Human; class Dog; class Cat; class Human: public O<Human, Dog>, public O<Human, Cat> {}; class Dog: public O<Dog, Human> {}; class Cat: public O<Cat, Human> {};
SetLink
in order to SetLink
function from the correct base class. The attentive reader will notice that the compiler could choose the correct SetLink()
function according to the type of the parameter passed to it, as is done in the case of overloaded functions. However, if these functions are in different classes (in our case, in different parent classes), then according to the C ++ standard, overloading does not work [1]. Human* h; Dog* d; Cat* c; ... // h->SetLink(d); // , h->O<Human, Dog>::SetLink(d); //, h->O<Human, Cat>::SetLink(c); // // GetLink() // h->GetLink(); //, Link - h->O<Human, Dog>::GetLink(); //,
SetLink()
implementations of the own SetLink()
and GetLink()
methods, which will call the corresponding method of one or another parent class depending on the type: class Human: public O<Human, Dog>, public O<Human, Cat> { public: template<class T> const T* GetLink() const { return O<Human,T>::GetLink(); } template<class T> void SetLink(T* l) { O<Human,T>::SetLink(l); } };
Human* h; Dog* d; Cat* c; ... h->SetLink<Dog>(d); h->SetLink<Cat>(c); // , h->SetLink(d); h->SetLink(c); h->GetLink<Dog>(); // Dog h->GetLink<Cat>(); // Cat
Source: https://habr.com/ru/post/126501/
All Articles