Jeśli zadeklaruję klasę bazową (lub klasę interfejsu) i określę wartość domyślną dla co najmniej jednego z jej parametrów, czy klasy pochodne muszą określać te same wartości domyślne, a jeśli nie, to które wartości domyślne będą widoczne w klasach pochodnych?
Dodatek: Interesuje mnie również, jak można to załatwić w różnych kompilatorach, oraz wszelkie dane wejściowe dotyczące „zalecanych” praktyk w tym scenariuszu.
Odpowiedzi:
Wirtualne mogą mieć wartości domyślne. Wartości domyślne w klasie bazowej nie są dziedziczone przez klasy pochodne.
To, która wartość domyślna jest używana - tj. Klasa bazowa „czy klasa pochodna” - jest określane przez typ statyczny użyty do wywołania funkcji. Jeśli wywołujesz za pośrednictwem obiektu klasy bazowej, wskaźnika lub odwołania, używana jest wartość domyślna oznaczona w klasie bazowej. I odwrotnie, jeśli wywołujesz za pośrednictwem obiektu klasy pochodnej, używany jest wskaźnik lub odwołanie, wartości domyślne oznaczone w klasie pochodnej. Pokazuje to przykład poniżej standardowego cytatu.
Niektóre kompilatory mogą zrobić coś innego, ale tak mówią standardy C ++ 03 i C ++ 11:
Oto przykładowy program pokazujący, jakie ustawienia domyślne są pobierane. Używam
struct
tutaj znaków s zamiastclass
es po prostu dla zwięzłości -class
istruct
są one dokładnie takie same pod każdym względem, z wyjątkiem domyślnej widoczności.Dane wyjściowe tego programu (na MSVC10 i GCC 4.4) to:
źródło
To był temat jednego z pierwszych postów Guru Tygodnia Herba Suttera .
Pierwszą rzeczą, jaką mówi na ten temat, jest: NIE ROBIĆ TEGO.
Bardziej szczegółowo, tak, możesz określić różne parametry domyślne. Nie będą działać tak samo, jak funkcje wirtualne. Funkcja wirtualna jest wywoływana dla typu dynamicznego obiektu, podczas gdy domyślne wartości parametrów są oparte na typie statycznym.
Dany
powinieneś otrzymać A :: foo1 B :: foo2 B :: foo1
źródło
To zły pomysł, ponieważ domyślne argumenty, które otrzymasz, będą zależały od statycznego typu obiektu, podczas gdy
virtual
funkcja wysyłana do będzie zależała od typu dynamicznego .Oznacza to, że kiedy wywołujesz funkcję z domyślnymi argumentami, domyślne argumenty są zastępowane w czasie kompilacji, niezależnie od tego, czy funkcja jest,
virtual
czy nie.@cppcoder podał następujący przykład w swoim [zamkniętym] pytaniu :
Który daje następujący wynik:
Na podstawie powyższego wyjaśnienia łatwo zrozumieć, dlaczego. W czasie kompilacji kompilator zastępuje domyślne argumenty z funkcji składowych typów statycznych wskaźników, dzięki czemu
main
funkcja jest równoważna z poniższym:źródło
Jak widać z innych odpowiedzi, jest to skomplikowany temat. Zamiast próbować to zrobić lub zrozumieć, co robi (jeśli będziesz musiał zapytać teraz, opiekun będzie musiał zapytać lub sprawdzić to za rok od teraz).
Zamiast tego utwórz publiczną niewirtualną funkcję w klasie bazowej z domyślnymi parametrami. Następnie wywołuje prywatną lub chronioną funkcję wirtualną, która nie ma parametrów domyślnych i jest zastępowana w klasach potomnych w razie potrzeby. Wtedy nie musisz martwić się o szczegóły, jak to będzie działać, a kod jest bardzo oczywisty.
źródło
Jest to taki, który prawdopodobnie możesz dość dobrze zrozumieć, testując (tj. Jest to wystarczająco mainstreamowa część języka, że większość kompilatorów prawie na pewno dobrze to rozumie i jeśli nie widzisz różnic między kompilatorami, ich wynik można uznać za całkiem autorytatywny).
źródło
Jak podają inne odpowiedzi, jest to zły pomysł. Ponieważ jednak nikt nie wspomina o prostym i skutecznym rozwiązaniu, oto jest: Konwertuj parametry na strukturę, a wtedy możesz mieć wartości domyślne na składowe struktury!
Więc zamiast
Zrób to,
źródło