Słowo kluczowe ‘base’

2007-09-24 17:51

Z dobrodziejstwa metod wirtualnych po prostu nie można nie korzystać. Dzięki nim kod jest bardziej elegancki, krótki, często (wbrew powszechnej opinii) efektywniejszy i naturalnie bardziej obiektowy :) Wszystkie te zalety opierają się oczywiście na tym, że tak naprawdę nie musimy wiedzieć, jaką wersję metody wirtualnej – oryginalną czy nadpisaną w klasie pochodnej – wywołujemy w danym przypadku.
Sama metoda aczkolwiek ‘wie’ to doskonale. Czasami zdarza się jednak, że chcielibyśmy wywołać jej odziedziczoną wersję, pochodzącą z klasy bazowej. Podobnie jak większość języków, C++ nie czyni tego automatycznie (z wyjątkiem konstruktorów i destruktorów), jako że nie zawsze jest to potrzebne. Ale nierzadko się przydaje i jest wygodne.

W wielu językach, jak choćby Delphi czy C#, mamy pomocnicze słowa kluczowe, służące do takich właśnie wywołań. W przeciwieństwie do nich C++ oferuje jednak dziedziczenie wielokrotne, wobec tego czasami klasa bazowa nie jest określona jednoznacznie. Dlatego też chcąc wywołać odziedziczoną wersję metody, musimy jawnie użyć nazwy tej klasy., np.:

  1. class CFoo { public: virtual void Do() { /* ... */ } };
  2.  
  3. class CBar : public CFoo
  4. {
  5.    public:
  6.       void Do()
  7.       {
  8.          // ...
  9.          CFoo::Do();   // wywołanie odziedziczonej wersji metody
  10.       }
  11. };

Wielodziedziczenia używamy jednak rzadko i w zdecydowanej większości sytuacji klasa bazowa będzie tylko jedna. Na takie okazje Visual C++ przewidział własne słowo kluczowe __super. Możemy też pokusić się o bardziej przenośne rozwiązanie, definiując taki oto szablon:

  1. template <class T> class Inherits : public T
  2. {
  3.    protected:
  4.       typedef T base;
  5. };

a wówczas zyskamy swoje własne “słowo kluczowe” base o możliwościach podobnych do tych z C#:

  1. class CBar : public Inherits<CFoo>
  2. {
  3.    public:
  4.       void Do()   { /* ... */   base::Do(); }
  5. };

Na nieszczęście jest tu mnóstwo różnych “ale”. Największym problemem jest to, że właściwej klasy bazowej (tutaj CFoo) nie ma jak zainicjalizować w klasie pochodnej, wobec czego musi ona dysponować domyślnym konstruktorem, który na dodatek będzie używany zawsze. To poważny feler, którego nie ma za bardzo jak naprawić. Dlatego jeśli bardzo doskwiera nam brak słowa base, to chyba jedynym sposobem jest… ręczne dodawanie typedefa podobnego do tego w szablonie Inherits.
Dopiero C++0x wprowadzi możliwość dziedziczenia konstruktorów (na zasadzie przekierowywania ich parametrów do klasy bazowej), która pozwoli wyeliminować wspomniane ograniczenie. Wówczas taka wersja szablonu:

  1. template <class T> class Inherits : public T
  2. {
  3.    protected:
  4.       typedef T base;
  5.    public:
  6.       // polecenie odziedziczenia konstruktorów z klasy T
  7.       using T::T;
  8. };

powinna zdać egzamin dla dowolnej klasy T.

Tags: , ,
Author: Xion, posted under Programming »



Adding comments is disabled.

Comments are disabled.
 


© 2018 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.