Odpowiedź na pytanie, dlaczego umieszczamy prywatne zmienne składowe w nagłówkach C ++, jest taka, że rozmiar klasy musi być znany w punktach, w których deklarowane są instancje, aby kompilator mógł wygenerować kod, który odpowiednio porusza się po stosie.
Dlaczego musimy umieszczać prywatnych członków w nagłówkach?
Ale czy istnieje jakikolwiek powód do deklarowania funkcji prywatnych w definicji klasy?
Alternatywą byłby zasadniczo idiom pimpl, ale bez zbędnej pośredniczości.
Czy ta funkcja języka jest czymś więcej niż błędem historycznym?
Jeśli zezwoliłeś, aby metody były dodawane do klasy poza jej definicją, mogą być dodawane w dowolnym miejscu , w dowolnym pliku, przez kogokolwiek.
To natychmiast dałoby wszystkim kodom klienta trywialny dostęp do prywatnych i chronionych członków danych.
Po zakończeniu definicji klasy nie ma możliwości oznaczenia niektórych plików jako specjalnie pobłogosławionych przez autora, aby je rozszerzyć - są tylko płaskie jednostki tłumaczeniowe. Zatem jedynym rozsądnym sposobem poinformowania kompilatora, że określony zestaw metod jest oficjalny lub pobłogosławiony przez autora klasy, jest zadeklarowanie ich w klasie.
Zauważ, że mamy bezpośredni dostęp do pamięci w C ++, co oznacza, że generalnie trywialne jest tworzenie typu cienia z tym samym układem pamięci co klasa, dodawanie własnych metod (lub po prostu upublicznianie wszystkich danych) i
reinterpret_cast
. Albo mogę znaleźć kod twojej prywatnej funkcji lub go zdemontować. Lub wyszukaj adres funkcji w tablicy symboli i wywołaj lub bezpośrednio.Te specyfikatory dostępu nie próbują zapobiegać tym atakom, ponieważ nie jest to możliwe. Wskazują tylko, w jaki sposób ma być używana klasa.
źródło
Przyjęta odpowiedź wyjaśnia to w przypadku wirtualnych funkcji prywatnych, ale to odpowiada tylko na jeden konkretny aspekt pytania, który jest znacznie bardziej ograniczony niż to, o co pytał PO. Tak więc musimy przeformułować: Dlaczego musimy zadeklarować nie-wirtualne funkcje prywatne w nagłówkach?
Inna odpowiedź przywołuje fakt, że klasy muszą być zadeklarowane w jednym bloku - po czym są zapieczętowane i nie można do nich dodawać. To właśnie robisz, pomijając deklarację prywatnej metody w nagłówku, a następnie próbując zdefiniować ją gdzie indziej. Niezły punkt. Dlaczego niektórzy użytkownicy tej klasy powinni mieć możliwość rozszerzenia tego w sposób, którego inni użytkownicy nie mogą zaobserwować? Metody prywatne są jego częścią i nie są z tego wyłączone. Ale pytasz, dlaczego są uwzględnione, i wydaje się to trochę tautologiczne. Dlaczego użytkownicy klas muszą o nich wiedzieć? Gdyby nie były widoczne, użytkownicy nie mogliby ich dodać i hej presto.
Chciałem więc udzielić odpowiedzi, która zamiast domyślnie uwzględniać metody prywatne, zapewnia określone punkty na korzyść ich widoczności dla użytkowników. Mechanistyczny powód nie-wirtualnych funkcji prywatnych wymagających publicznej deklaracji podano w GotW # 100 Herb Suttera na temat idiomu Pimpl w ramach jego uzasadnienia. Nie będę tu mówił o Pimplu, bo jestem pewien, że wszyscy o tym wiemy. Ale oto odpowiedni fragment:
Sutter jest oczywiście niezwykle wiarygodnym źródłem jako członek Komitetu, więc zna „świadomą decyzję projektową”, kiedy ją widzi. Pomysł wymagający publicznego zadeklarowania prywatnych metod jako sposobu uniknięcia późniejszej zmienionej semantyki lub przypadkowo uszkodzonej dostępności jest prawdopodobnie najbardziej przekonującym uzasadnieniem. Na szczęście, ponieważ cała ta sprawa wydawała się wcześniej bezcelowa!
źródło
Są dwa powody, aby to zrobić.
Po pierwsze, uświadom sobie, że specyfikator dostępu jest przeznaczony dla kompilatora i nie ma znaczenia w czasie wykonywania. Dostęp do członka prywatnego poza zakresem jest błędem kompilacji .
Zwięzłość
Rozważ funkcję krótką, jedną lub dwie linie. Istnieje, aby ograniczyć replikację kodu w innym miejscu, co ma tę zaletę, że może zmienić sposób działania algorytmu lub cokolwiek innego w jednym miejscu zamiast w wielu (np. Zmiana algorytmu sortowania).
Czy wolałbyś mieć jedną lub dwie linie w nagłówku, czy mieć prototyp funkcji i implementację? Łatwiej jest znaleźć w nagłówku, a dla krótkich funkcji o wiele bardziej gadatliwa jest osobna implementacja.
Jest jeszcze jedna ważna zaleta, którą jest ...
Funkcje wbudowane
Funkcja prywatna może być wstawiana, a to koniecznie wymaga umieszczenia jej w nagłówku. Rozważ to:
Funkcja prywatna może być zintegrowana z funkcją publiczną. Odbywa się to według uznania kompilatora, ponieważ
inline
słowo kluczowe jest technicznie sugestią , a nie wymogiem.źródło
inline
, nie ma powodu, aby używać słowa kluczowego..cpp
pliku funkcji innej niż członkowska , która jest wstawiana przez funkcje składowe zdefiniowane poza definicją klasy, ale taka funkcja nie byłaby prywatna.Kolejny powód posiadania prywatnych metod w pliku nagłówkowym: Istnieją przypadki, w których publiczna metoda wbudowana nie robi nic więcej niż wywoływanie jednej lub kilku metod prywatnych. Posiadanie metod prywatnych w nagłówku oznacza, że wywołanie metody publicznej może być całkowicie powiązane z rzeczywistym kodem metod prywatnych, a wstawianie nie kończy się na wywołaniu metody prywatnej. Nawet z innej jednostki kompilacji (a metody publiczne są zwykle wywoływane z różnych jednostek kompilacji).
Oczywiście istnieje również powód, dla którego kompilator nie może wykryć problemów z rozwiązaniem problemu przeciążenia, jeśli nie zna wszystkich metod, w tym prywatnych.
źródło
Ma to umożliwić tym funkcjom dostęp do prywatnych członków. W przeciwnym razie i tak będziesz potrzebować
friend
ich w nagłówku.Jeśli jakakolwiek funkcja mogłaby uzyskać dostęp do prywatnych członków klasy, private byłoby bezużyteczne.
źródło