Jak rozpoznać, który scenariusz zajdzie podczas kompilacji? Mogą się stać 3 rzeczy:
a) B::XYZ będzie overridem dla A::XYZ
b) Poleci błąd kompilatora
c) Kod skompiluje się, ale B::XYZ nie będzie overridem dla A::XYZ
Mój punkt widzenia:
1) Sprawdzamy ilość i typy argumentów. B::XYZ Musi być *dokładnie* taka sama jeśli chodzi o typy - z moich eksperymentów wynika że żadne superklasy i subklasy nie mają tu znaczenia, każda różnica powoduje od razu scenariusz C - czyli cichy bug, którego szuka się debuggerem tydzień :). Wyjątek: B::XYZ może zaproponować wartości domyślne dla argumentów, czyli f(int a) można overridować za pomocą f(int a=5).
2) Jeśli pkt 1 przeszedł, sprawdzamy typ zwracany. Jeśli są takie same LUB typ zwracany B::XYZ jest covariant z typem zwracanym przez A::XYZ, to otrzymujemy scenariusz A. W przeciwnym wypadku otrzymujemy scenariusz B z błędem w stylu "invalid covariant return type for `virtual Typ B::XYZ()'".
Pytanie 1: Co dokładnie znaczy covariant w tym kontekście? Jeśli A zwraca wskaźnik/referencję na obiekt jakiejś klasy, to na pewno możemy zaostrzyć wymagania oferując w B wskaźnik/referencję na obiekt subklasy. Wskaźnik na void* możemy doprecyzować wskaźnikiem na cokolwiek. Czy są jakieś inne opcje?
Pytanie 2: Czy specyfikatory dostępu (są tu trzy: przy metodzie A::XYZ, przy metodzie B::XYZ i przy dziedziczeniu B:A) mają w tym procesie JAKIEKOLWIEK znaczenie? Wydaje mi się to dziwne, bo nie dostrzegłem nic takiego - nawet, jeśli metodę private overridujemy metodą public przy dziedziczeniu prywatnym! Bardzo mnie to zdziwiło. A może coś pokręciłem?
Wszelkie dokładne doprecyzowania mile widziane.
Warsztat