IMHO, istniejące odpowiedzi słabo wyjaśniają „dlaczego” tego - koncentrując się zbytnio na powtarzaniu, jakie zachowanie jest prawidłowe. „modyfikatory dostępu działają na poziomie klasy, a nie obiektu”. - tak ale dlaczego?
Nadrzędną koncepcją jest tutaj to, że to programista (programiści) projektujący, piszący i utrzymujący klasę powinien (powinni) rozumieć enkapsulację obiektową pożądaną i uprawnioną do koordynowania jej implementacji. Tak więc, pisząc class X
, kodujesz nie tylko to, jak pojedynczy X x
obiekt może być używany przez kod z dostępem do niego, ale także:
- klasy pochodne są w stanie współdziałać z nim (za pośrednictwem opcjonalnie czystych funkcji wirtualnych i / lub chronionego dostępu) i
- różne
X
obiekty współpracują w celu zapewnienia zamierzonych zachowań, jednocześnie przestrzegając warunków końcowych i niezmienników z projektu.
To nie tylko konstruktor kopiujący - bardzo wiele operacji może obejmować dwie lub więcej instancji Twojej klasy: jeśli porównujesz, dodajesz / mnożesz / dzielisz, kopiujesz konstruowanie, klonowanie, przypisywanie itp., To często jest tak, że albo po prostu musi mieć dostęp do prywatnych i / lub chronionych danych w innym obiekcie, albo chce, aby umożliwiał prostszą, szybszą lub ogólnie lepszą implementację funkcji.
W szczególności te operacje mogą chcieć skorzystać z uprzywilejowanego dostępu, aby wykonać następujące czynności:
- (konstruktory kopiujące) używają prywatnego elementu członkowskiego obiektu "rhs" (po prawej stronie) na liście inicjalizatorów, tak że zmienna składowa jest sama konstruowana przez kopiowanie zamiast konstruowana domyślnie (jeśli nawet legalna), a następnie przypisywana (ponownie, jeśli legalne)
- współdziel zasoby - uchwyty plików, segmenty pamięci współdzielonej,
shared_ptr
s do danych referencyjnych itp.
- przejąć na własność rzeczy, np.
auto_ptr<>
„przenosi” własność na obiekt w budowie
- kopiuj prywatne "pamięci podręczne", elementy kalibracji lub stanu potrzebne do skonstruowania nowego obiektu w optymalnie użytecznym stanie bez konieczności ponownego generowania ich od podstaw
- kopiuj / uzyskuj dostęp do informacji diagnostycznych / śledzenia przechowywanych w kopiowanym obiekcie, które nie są w inny sposób dostępne za pośrednictwem publicznych interfejsów API, ale mogą być używane przez jakiś późniejszy obiekt wyjątku lub rejestrowanie (np. informacje dotyczące czasu / okoliczności, w których „oryginalna” nie utworzona kopia został zbudowany)
- wykonać bardziej wydajną kopię niektórych danych: np. obiekty mogą mieć np.
unordered_map
członka, ale publicznie tylko ujawniają begin()
i end()
iteratory - z bezpośrednim dostępem do size()
ciebie można reserve
by przyspieszyć kopiowanie; Co gorsza, jeśli tylko oni wystawiać at()
i insert()
a inaczej throw
....
- skopiuj odniesienia z powrotem do obiektów nadrzędnych / koordynacyjnych / zarządzających, które mogą być nieznane lub przeznaczone tylko do zapisu dla kodu klienta