Za kulisami publicznego, prywatnego i chronionego

Dec 08 2020

Staram się zanurkować głębiej i zrozumieć różnice między Public | Prywatne | Chronione z perspektywy niskiego poziomu, w C ++.

W jaki sposób różnice między trzema wyrażają się w pamięci?

Odpowiedzi

5 largest_prime_is_463035818 Dec 08 2020 at 20:48

private, publicI protectednie powoduje członkowie mają być przechowywane w określonych regionach pamięci. Dostęp jest sprawdzany przez kompilator. Na najniższym poziomie nie ma różnicy.

Jednak specyfikatory dostępu mają wpływ na to, co gwarantuje, że uzyskasz kolejność, w jakiej elementy członkowskie klasy są rozmieszczone w pamięci.

Ze standardowej wersji roboczej C ++ 17 :

Niestatyczne składowe danych klasy (nie-unii) z tą samą kontrolą dostępu (klauzula [class.access]) są przydzielane, aby późniejsi członkowie mieli wyższe adresy w obiekcie klasy. Kolejność przydzielania niestatycznych składowych danych z różną kontrolą dostępu jest nieokreślona (klauzula [klasa.access]). Wymagania dotyczące dostosowania implementacji mogą spowodować, że dwóch sąsiednich członków nie zostanie przydzielonych bezpośrednio po sobie; tak może być wymagania dotyczące przestrzeni do zarządzania funkcjami wirtualnymi ([class.virtual]) i wirtualnymi klasami bazowymi ([class.mi]).

Oznacza to, że dla

 struct foo {
     private:
        int x;
     protected:
        int a;
        int b;
     public:
        int m;
        int n;
     private:
        int y;
};

Masz tylko gwarancję, że pamięć xjest wcześniej y, apoprzedza bi mpoprzedza n. Poza tym kolejność, w jakiej członkowie są ułożeni w pamięci, jest nieokreślona.

Jednak rzadko kolejność członków w pamięci jest użyteczną informacją. Dlatego nie jest błędem stwierdzenie, że specyfikatory dostępu nie mają nic wspólnego z „pamięcią niskiego poziomu”.

2 SergeBallesta Dec 08 2020 at 20:44

Na najniższym poziomie (reprezentacja obiektów w bajtach) nie ma absolutnie żadnej różnicy między publicznym, prywatnym i chronionym. W większości kompilatory mogą (ale nie muszą) zmieniać kolejności członków zgodnie z ich widocznością.

Na poziomie pośrednim (zachowanie w czasie wykonywania) różnica jest niewielka, jeśli w ogóle. Jeśli możesz znaleźć publiczny wskaźnik do prywatnych danych, możesz z nich bezpiecznie korzystać. W szczególności różni się to od constness, w którym użycie wskaźnika innego niż const do zmiany danych const jest jawnie niezdefiniowanym zachowaniem i może powodować błędy SIGSEGV.

Różnica jest tylko na najwyższym poziomie. Możesz używać publicznych członków z dowolnego miejsca, podczas gdy prywatni członkowie mogą być używane tylko w klasie, w której są zadeklarowani, a chroniony element członkowski może być używany z ich klasy i wszystkich klas dziedziczących - ale przyjaźń może umożliwić określonym klasom funkcji dostęp do prywatnych lub chronionych dane.

Yunnosch Dec 08 2020 at 20:35

Ani trochę.

Kompilator przyznaje / odmawia dostępu.

Każdy dostęp, który nie pasuje do odpowiedniej widoczności (kontrolowanej przez klasę obiektu, do którego uzyskiwany jest dostęp, za pomocą wskaźnika lub nie) jest blokowany przed budowaniem.

Uwaga:

Inne odpowiedzi pożytecznie omawiają wpływ widoczności na porządek w pamięci.

Jakkolwiek odpowiedziałem na inne pytanie, które przeczytałem w postach PO „W jaki sposób funkcje ochrony pamięci są wykorzystywane do implementacji dostępności / widoczności członków?”, Które dotyczące przyczyny i skutku jest pytaniem odwrotnym. Lub tylko uporządkowanie / ustrukturyzowanie elementów w różnie skonfigurowanych pamięciach jest narzędziem do osiągnięcia pożądanego efektu widoczności, co z kolei wymagałoby (ale nie powodowałoby) uporządkowania elementów w określony sposób.

Tzn. Nie widzę konfliktu między odpowiedziami, tylko inną interpretację pytania.