[ Pobierz całość w formacie PDF ]
.8.Klasy i funkcje wirtualneDziedziczenie mnogie mo¿e byæ œrodkiem dla organizacji bibliotek wokó³prostszych klas z mniejsz¹ liczb¹ zale¿noœci pomiêdzy klasami, ni¿ w przypadkudziedziczenia pojedynczego.Gdyby ograniczyæ dziedziczenie do pojedynczego, toka¿da biblioteka by³aby jednym drzewem dziedziczenia, w ogólnoœci bardzowysokim i rozga³êzionym.Mechanizm dziedziczenia mnogiego pozwala budowaæbiblioteki w postaci „lasu mieszanego”, w którym drzewa i grafy dziedziczeniamog¹ mieæ zmienn¹ liczbê poziomów i rozga³êzieñ.Z przeprowadzonej w r.7dyskusji wynika, ¿e takie struktury mo¿na tworzyæ stosunkowo ³atwo, gdy klasapochodna dziedziczy w³asnoœci kilku niezale¿nych (roz³¹cznych) klas bazowych,nie maj¹cych wspólnej superklasy.Je¿eli jednak bezpoœrednie klasy bazowe danejklasy pochodnej s¹ zale¿ne, nale¿y zastosowaæ omówione ni¿ej mechanizmyjêzykowe.8.1.Wirtualne klasy bazowePrzedstawiony w p.7.3 przyk³ad ilustruje niejednoznacznoœci, jakie mog¹ siêpojawiæ w hierarhii dziedziczenia, gdy klasa pochodna dziedziczy tê sam¹ klasêbazow¹ kilkakrotnie, id¹c po ró¿nych krawêdziach grafu dziedziczenia.Odwo³aniado elementów sk³adowych takiej klasy bazowej s¹ wówczas mo¿liwe, ale k³opotliwe(np.obiekt.Pochodna1::a).Jêzyk C++ oferuje tutaj mechanizm, dziêki któremu“klasy siostrzane” wspó³dziel¹ informacjê (w tym przypadku jeden obiektwspólnej klasy bazowej) bez wp³ywu na inne klasy w grafie dziedziczenia.Mechanizm ten polega na potraktowaniu wspólnej klasy bazowej jako klasywirtualnej w klasach “siostrzanych”, a przywo³uje siê go, pisz¹c s³owo kluczowevirtual przed lub po specyfikatorze dostêpu, a przed nazw¹ klasy bazowej.Wirtualnoœæ wspólnej klasy bazowej jest w³asnoœci¹ stosowanego schematudziedziczenia, a nie samej klasy, która poza tym niczym siê nie ró¿ni od klasyniewirtualnej.Je¿eli przy dziedziczeniu mnogim klasa pochodna dziedziczy têsam¹ klasê bazow¹ jako wirtualn¹ i – id¹c po innej ga³êzi – jako niewirtualn¹,to oczywiœcie niejednoznacznoœci nie usuniemy.Ilustracj¹ tego jest rysunek8-1, który pokazuje schemat dziedziczenia z wirtualnymi i niewirtualnymiklasami bazowymi.Rys.8-1 Dziedziczenie mnogie z wirtualnymi klasami bazowymiW prezentowanym grafie dziedziczenia le¿¹ca najni¿ej w hierarchii klasapochodna Z dziedziczy cechy szeœciu swoich klas bazowych, przy czym klasy F, C,D i E s¹ jej bezpoœrednimi klasami bazowymi, zaœ A i B – poœrednimi.Klasy B iE wspó³dziel¹ jeden obiekt klasy A, poniewa¿ klasa A jest w ka¿dej z nichdeklarowana jako wirtualna klasa bazowa.Natomiast ka¿dy obiekt klas C i Dbêdzie zawieraæ w³asn¹ kopiê zmiennych sk³adowych klasy A.W rezultacie ka¿dyobiekt klasy Z bêdzie zawieraæ trzy kopie zmiennych sk³adowych klasy A: jedn¹przez dwie ga³êzie wirtualne (przez E i B/F) i po jednej z ga³êzi C i D.Pokazany schemat mo¿na opisaæ przyk³adowymi deklaracjami:class A {public:void f() { cout f();chocia¿ i w tym przypadku mo¿emy wo³aæ funkcjê f() poprzez adresy obiektów klaspoœrednich:wsk->C::f();wsk->D::f();wsk->E::f();wsk->F::f();Wszystkie powy¿sze wywo³ania poœrednie maj¹ sk³adniê raczej ma³o zachêcaj¹c¹.Gdyby w klasie A zadeklarowaæ zmienne sk³adowe, to odwo³ania do nich by³ybypodobne.Oczywistym sposobem usuniêcia niejednoznacznoœci z dyskutowanego schematuby³oby zadeklarowanie klasy A jako wirtualnej klasy bazowej w pozosta³ychklasach poœrednich, tj.C i D.Takie w³aœnie za³o¿enie przyjêto w prezentowanymni¿ej programie, który korzysta ze znacznie prostszego schematu dziedziczenia.Przyk³ad 8.1.Schemat dziedziczenia: Bazowa/ \/ \Pochodna1 Pochodna2\ /\ /DwieBazy#includeclass Bazowa {public:Bazowa(): a(0) {}int a;};class Pochodna1: virtual public Bazowa {public:Pochodna1(): b(0) {}int b;};class Pochodna2: virtual public Bazowa {public:Pochodna2(): c(0) {}int c;};class DwieBazy: public Pochodna1, public Pochodna2 {public:DwieBazy() {}int iloczyn() { return a*b*c; }};int main() {DwieBazy obiekt;obiekt.a = 4; obiekt.b = 5; obiekt.c = 6;cout
[ Pobierz całość w formacie PDF ]
Darmowy hosting zapewnia PRV.PL