oj.. widzisz.. dziedziczenie i prawa dostepu nie sa tak trywialne jak by sie zdawac moglo!
achtung: visual studio 2008, IMHO, w tym przypadku zachowanie 100% zgodne z std. ale przyznam, nie sprawdzalem.. porownuje z wlasna pamieci
btw. specjalnie okroilem kod do minimum ktore eksponuje te same problemy - np. wywalilem WHorse::work, ktore NIC nie zmienia w kontekscie proby pobrania wskaznika na basew::work
kod:
class BaseW
{
protected: ///#
int work( int a, int b ) { return b; }
int x;
};
class Test : public BaseW { };
class WHorse : public BaseW
{
public:
/// ---pastehere---
};
wynik: kompiluje sie.
a teraz 'wcinki' - metody z przykladow wklej w zaznaczone miejsce
przyklad 1)
void test1()
{
int c;
c = work( 2, c ); ///1
c = BaseW::work( 2 ,3 ); ///2
}
wynik kompilacji: ok
info:
- w miejscu (1) klasa WHorse (:public BaseW => protected base members 'widoczne' jako protected, dziedziczenie public nic zmienilo) ma prawo wywolac odziedziczona metode, konkretnie - wywolac metode 'work' ktora zostanie przetlumaczona na 'basew::work', gdyz WHorse nie definiuje wlasnej metody work.
- w miejscu (2) klasa WHorse ma prawo wywolac metode basew::work na dokladnie tych samych prawach. linie (1) i (2) niczym sie nie roznia!
przyklad 2)
void test2()
{
typedef int (BaseW::*wrk)( int, int );
wrk pointer = &BaseW::work; //3
}
wynik kompilacji: blad
1>Compiling...
1>x.cpp
1>c:\poligon\4p\137015\x.cpp(15) : error C2248: 'BaseW::work' : cannot access protected member declared in class 'BaseW'
1> c:\poligon\4p\137015\x.cpp(4) : see declaration of 'BaseW::work'
1> c:\poligon\4p\137015\x.cpp(2) : see declaration of 'BaseW'
info:
- w miejscu (3) klasa WHorse nie ma prawa dobierac sie do metody work. metoda ta nie jest widziana jako publiczna i nikt, ale to nikt poza klasa BaseW nie ma prawa operowac na niej, za wyjatkiem:
--- jej friends, ktore maja taki sam dostep do wszystkiego jak ona sama
--- dzieci, ktorym zezwala sie na wywolywanie jej metod w kontekscie obiektow swojej klasy [patrz przyklad 3] i odczyt/zapis jej pol [patrz przyklad 4]
przyklad 3)
void test3()
{
work(1, 1); ///4
Test ttt;
WHorse hhh;
hhh.work(1, 1); ///7
ttt.work(1, 1); ///5
BaseW* ptr = &ttt;
ptr->work(1,1); ///6
}
wynik kompilacji: blad
1>Compiling...
1>x.cpp
1>c:\poligon\4p\137015\x.cpp(16) : error C2248: 'BaseW::work' : cannot access protected member declared in class 'BaseW'
1> c:\poligon\4p\137015\x.cpp(4) : see declaration of 'BaseW::work'
1> c:\poligon\4p\137015\x.cpp(2) : see declaration of 'BaseW'
1>c:\poligon\4p\137015\x.cpp(18) : error C2248: 'BaseW::work' : cannot access protected member declared in class 'BaseW'
1> c:\poligon\4p\137015\x.cpp(4) : see declaration of 'BaseW::work'
1> c:\poligon\4p\137015\x.cpp(2) : see declaration of 'BaseW'
info:
- w miejscu oznaczonym (5) okazuje sie ze .. WHorse nie ma prawa do metody work! czemu? poniewaz 'protected' dla member'a z bazy mowi, ze dzieci maja prawo ja wywolac w kontekscie swojej klasy. Klasa WHorse nie ma nic do klasy Test!
- jak widac pare linii nizej, w miejscu (6) - nawet chamska proba przerzutowania Test na BaseW i wywolania metody work w scopie klasy BaseW sie nie udaje --- scope klasy BaseW to nie scope WHorse, wiec nie ma tutaj prawa wywolania.
- i jak widac na miejscu (4) i (7) ktorego kompilator sie nie czepia, wolanie basew::work w scopie WHorse jest poprawne
przyklad 4)
void test4()
{
x = 1; ///4'
WHorse hhh;
hhh.x = 1; ///7'
Test ttt;
ttt.x = 1; ///5'
BaseW* ptr = &ttt;
ptr->x = 1; ///6'
}
wynik kompilacji: blad
1>Compiling...
1>x.cpp
1>c:\poligon\4p\137015\x.cpp(19) : error C2248: 'BaseW::x' : cannot access protected member declared in class 'BaseW'
1> c:\poligon\4p\137015\x.cpp(5) : see declaration of 'BaseW::x'
1> c:\poligon\4p\137015\x.cpp(2) : see declaration of 'BaseW'
1>c:\poligon\4p\137015\x.cpp(21) : error C2248: 'BaseW::x' : cannot access protected member declared in class 'BaseW'
1> c:\poligon\4p\137015\x.cpp(5) : see declaration of 'BaseW::x'
1> c:\poligon\4p\137015\x.cpp(2) : see declaration of 'BaseW'
info:
- jak widac, sytuacje (4'/5'/6'/7') dla proby zapisu protected pol klasy bazowej daja dokladnie taki sam efekt jak w przykladzie 3) dla sytuacij analogicznych
przyklad 5) - juz tylko dla formalnosci
void test5()
{
typedef int (BaseW::*zmienna);
zmienna pointer = &BaseW::x; //8
}
wynik kompilacji: blad
1>Compiling...
1>x.cpp
1>c:\poligon\4p\137015\x.cpp(16) : error C2248: 'BaseW::x' : cannot access protected member declared in class 'BaseW'
1> c:\poligon\4p\137015\x.cpp(5) : see declaration of 'BaseW::x'
1> c:\poligon\4p\137015\x.cpp(2) : see declaration of 'BaseW'
info:
- jak sie mozna bylo spodziewac, WHorse nie ma dostepu do x w scopie BaseW w miejscu (8)
ale ale ale.. troche pomyslmy: przeciez dziedziczenie (ktore jest wrecz :public) mowi, ze WHorse jest BaseW i ze posiada metode work (ktora bedzie dla 'klientow klasy' widoczna jako protected, tak jak w bazie)
...wiec... uwaga.. to bedzie proste, ale i zawile:
skoro WHorse odziedziczylo work to .. WHorse ma metode work.
przyklad 6)
void test6()
{
typedef int (WHorse::*zmienna);
zmienna pointer = &WHorse::x; //9
}
void test7()
{
typedef int (WHorse::*wrk)( int, int );
wrk pointer = &WHorse::work; //10
}
wynik kompilacji: ok
info:
- czego to dowodzi? ano.. ze WHorse ma prawo operowac w 100% na swojej metodzie work, ktora, badz co badz dostalo z klasy bazowej.. ugh.
- to co naprawde ten przyklad pokazuje, to to, ze odwolywanie sie doczegos poprzez klase WHorse nie jest tym samym co przez BaseW, mimo ze WHorse jest obiektem BaseW. oznacza to wprost, ze mimo iz WHorse "to tez BaseW", to jednak scope klasy WHorse jest innym scopem niz BaseW, ma inne prawa niz on, i vice versa i.. reszte implikacji to juz moze zostawie do domyslu, bo moznaby ksiazke napisac pewnie
edit:
// edit: spróbowałem inny kompilator (borlanda) i jest OK, czyli jest to po prostu błąd w MinGW
z moich doswiadczen wynika, ze kompilatory Borlanda ..hm.. sa kiepskimi odwzorowaniami standardu. kompilatory z pod znaku gnu oraz, ptfu, microsoftu, trzymaja sie ich o wiele lepiej.
no, przynajmniej w tych podstawowych rzeczach nie tykajacych sie rozwiazywania zagmatwanych templateow.. tutaj podejrzewam ze i msoft i borland rowno odstaja i jedynie moze comeau jest ok:) niestety, jeszcze nie nabylem..