Menu
Coddy logo textTech

Specyfikatory dostępu — szczegółowo

Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 35 z 104.

Skoro rozumiesz już trzy specyfikatory dostępu, przyjrzyjmy się, jak działają, gdy masz wiele obiektów tej samej klasy. Powszechnym błędnym przekonaniem jest to, że private oznacza „tylko ten obiekt” — w rzeczywistości oznacza „tylko ta klasa”.

Obiekty tej samej klasy mogą uzyskiwać dostęp do swoich prywatnych składowych:

class Person {
    std::string secret;
    
public:
    Person(std::string s) : secret(s) {}
    
    void readSecret(const Person& other) {
        // Dostęp do prywatnego pola innego obiektu – dozwolony!
        std::cout << other.secret;
    }
};

Działa to, ponieważ kontrola dostępu jest egzekwowana na poziomie klasy, a nie obiektu. Metoda readSecret jest częścią klasy Person, więc może uzyskiwać dostęp do prywatnych składowych dowolnego obiektu Person. Taka konstrukcja umożliwia działanie operacji takich jak konstruktory kopiujące i operatory porównania, które korzystają ze stanu wewnętrznego innych obiektów.

Możesz też wielokrotnie przełączać się między specyfikatorami dostępu w obrębie klasy:

class Mixed {
public:
    void publicMethod1();
    
private:
    int privateData;
    
public:
    void publicMethod2();    // Z powrotem do public
    
private:
    void privateHelper();    // Ponownie private
};

Choć jest to poprawny kod C++, zazwyczaj lepiej grupować składowe według poziomu dostępu, aby zwiększyć czytelność. Większość przewodników po stylu zaleca wymienianie najpierw składowych publicznych (ponieważ tworzą interfejs klasy), następnie chronionych, a na końcu prywatnych.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system porównywania portfeli, który pokazuje, jak obiekty tej samej klasy mogą uzyskiwać dostęp do swoich prywatnych składowych. To ważna kwestia dotycząca kontroli dostępu w C++: jest ona egzekwowana na poziomie klasy, a nie obiektu.

Utworzysz dwa pliki, aby uporządkować kod:

  • Wallet.h: Zdefiniuj klasę Wallet, która przechowuje prywatne dane finansowe, ale umożliwia porównywanie portfeli. Twoja klasa powinna zawierać:
    • Prywatne składowe: ownerName (string) i balance (double)
    • Konstruktor, który przyjmuje nazwę właściciela i początkowe saldo
    • Publiczny getter getOwnerName(), który zwraca nazwę właściciela
    • Metodę hasMoreThan(const Wallet& other), która porównuje saldo tego portfela z prywatnym saldem innego portfela i zwraca true, jeśli ten portfel ma więcej pieniędzy
    • Metodę combinedBalance(const Wallet& other), która zwraca sumę prywatnych sald obu portfeli
    • Metodę transferTo(Wallet& other, double amount), która przenosi pieniądze z tego portfela do innego. Powinna bezpośrednio modyfikować prywatne salda obu portfeli (tylko jeśli kwota jest dodatnia i nie przekracza salda tego portfela)
  • main.cpp: Pokaż dostęp do prywatnych składowych innego obiektu. Wczytaj z wejścia dwie nazwy właścicieli i dwa salda (cztery wiersze: name1, balance1, name2, balance2), a następnie:
    • Utwórz dwa obiekty Wallet z wczytanymi wartościami
    • Wypisz "Combined wealth: $<amount>", używając combinedBalance()
    • Porównaj portfele i wypisz "<name> has more money" dla właściciela z wyższym saldem (użyj hasMoreThan(), aby to ustalić)
    • Przenieś 100.0 z pierwszego portfela do drugiego, używając transferTo()
    • Wypisz "After transfer:"
    • Ponownie wypisz "Combined wealth: $<amount>" (wartość powinna pozostać bez zmian)
    • Ponownie porównaj portfele i wypisz "<name> has more money" (wynik mógł się zmienić)

Kluczowa kwestia jest taka, że metody takie jak hasMoreThan() i transferTo() mogą bezpośrednio uzyskiwać dostęp do prywatnej składowej balance innego obiektu Wallet: nie są potrzebne gettery. Działa to dlatego, że kontrola dostępu w C++ jest oparta na klasach: dowolny kod wewnątrz klasy Wallet może uzyskiwać dostęp do prywatnych składowych dowolnego obiektu Wallet.

Formatuj wszystkie wartości pieniężne z dokładnością do dwóch miejsc po przecinku, używając std::fixed i std::setprecision(2) z <iomanip>. Konwertuj wczytane salda za pomocą std::stod().

Spróbuj swoich sił

#include <iostream>
#include <string>
#include <iomanip>
#include "Wallet.h"

using namespace std;

int main() {
    // Wczytaj dane wejściowe: name1, balance1, name2, balance2
    string name1, name2;
    string balanceStr1, balanceStr2;
    
    getline(cin, name1);
    getline(cin, balanceStr1);
    getline(cin, name2);
    getline(cin, balanceStr2);
    
    double balance1 = stod(balanceStr1);
    double balance2 = stod(balanceStr2);
    
    // Ustaw formatowanie wartości pieniężnych na wyjściu
    cout << fixed << setprecision(2);
    
    // TODO: Utwórz dwa obiekty Wallet z wartościami wejściowymi
    
    // TODO: Wypisz łączny stan środków, używając combinedBalance()
    // Format: "Combined wealth: $<amount>"
    
    // TODO: Porównaj portfele, używając hasMoreThan(), i wypisz, kto ma więcej pieniędzy
    // Format: "<name> has more money"
    
    // TODO: Przenieś 100.0 z pierwszego portfela do drugiego, używając transferTo()
    
    // TODO: Wypisz "After transfer:"
    
    // TODO: Ponownie wypisz łączny stan środków
    
    // TODO: Ponownie porównaj portfele i wypisz, kto ma więcej pieniędzy
    
    return 0;
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C++ online