Menu
Coddy logo textTech

Zugriffsspezifizierer im Detail

Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy — Lektion 35 von 104.

Nachdem Sie nun die drei Zugriffsspezifizierer verstehen, lassen Sie uns untersuchen, wie sie sich verhalten, wenn Sie mehrere Objekte derselben Klasse haben. Ein häufiges Missverständnis ist, dass private „nur dieses Objekt“ bedeutet – aber eigentlich bedeutet es „nur diese Klasse“.

Objekte derselben Klasse können auf die privaten Member der jeweils anderen zugreifen:

class Person {
    std::string secret;
    
public:
    Person(std::string s) : secret(s) {}
    
    void readSecret(const Person& other) {
        // Zugriff auf das private Member eines anderen Objekts - erlaubt!
        std::cout << other.secret;
    }
};

Dies funktioniert, weil die Zugriffskontrolle auf der Klassenebene erzwungen wird, nicht auf der Objektebene. Die Methode readSecret ist Teil der Klasse Person, sodass sie auf private Member jedes Person-Objekts zugreifen kann. Dieses Design ermöglicht es Operationen wie Kopierkonstruktoren und Vergleichsoperatoren, mit dem internen Zustand anderer Objekte zu arbeiten.

Sie können innerhalb einer Klasse auch mehrfach zwischen Zugriffsspezifizierern wechseln:

class Mixed {
public:
    void publicMethod1();
    
private:
    int privateData;
    
public:
    void publicMethod2();    // Zurück zu public
    
private:
    void privateHelper();    // Wieder private
};

Obwohl dies gültiges C++ ist, ist es im Allgemeinen besser, Member für eine bessere Lesbarkeit nach Zugriffsebene zu gruppieren. Die meisten Styleguides empfehlen, public Member zuerst aufzulisten (da sie die Klassenschnittstelle bilden), gefolgt von protected und dann private.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Wallet-Vergleichssystem erstellen, das demonstriert, wie Objekte derselben Klasse auf die privaten Member der jeweils anderen zugreifen können. Dies ist eine wichtige Erkenntnis über die Zugriffskontrolle in C++ — sie wird auf Klassenebene erzwungen, nicht auf Objektebene.

Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:

  • Wallet.h: Definieren Sie eine Wallet-Klasse, die private Finanzdaten speichert, aber Wallet-zu-Wallet-Vergleiche ermöglicht. Ihre Klasse sollte Folgendes enthalten:
    • Private Member: ownerName (string) und balance (double)
    • Einen Konstruktor, der den Namen des Besitzers und das Anfangsguthaben entgegennimmt
    • Einen öffentlichen Getter getOwnerName(), der den Namen des Besitzers zurückgibt
    • Eine Methode hasMoreThan(const Wallet& other), die das Guthaben dieses Wallets mit dem privaten Guthaben eines anderen Wallets vergleicht und true zurückgibt, wenn dieses Wallet mehr Geld hat
    • Eine Methode combinedBalance(const Wallet& other), die die Summe der privaten Guthaben beider Wallets zurückgibt
    • Eine Methode transferTo(Wallet& other, double amount), die Geld von diesem Wallet auf ein anderes überträgt — sie sollte die privaten Guthaben beider Wallets direkt ändern (nur wenn der Betrag positiv ist und das Guthaben dieses Wallets nicht übersteigt)
  • main.cpp: Demonstrieren Sie den objektübergreifenden Zugriff auf private Member. Lesen Sie zwei Besitzernamen und zwei Guthaben von der Eingabe ein (vier Zeilen: name1, balance1, name2, balance2) und führen Sie dann Folgendes aus:
    • Erstellen Sie zwei Wallet-Objekte mit den Eingabewerten
    • Geben Sie "Combined wealth: "Combined wealth: $"lt;amount>" unter Verwendung von combinedBalance() aus
    • Vergleichen Sie die Wallets und geben Sie "<name> has more money" für den Besitzer aus, der das höhere Guthaben hat (verwenden Sie hasMoreThan(), um dies zu bestimmen)
    • Übertragen Sie 100.0 vom ersten Wallet auf das zweite mit transferTo()
    • Geben Sie "After transfer:" aus
    • Geben Sie erneut "Combined wealth: "Combined wealth: $"lt;amount>" aus (sollte unverändert sein)
    • Vergleichen Sie erneut und geben Sie "<name> has more money" aus (das Ergebnis kann sich geändert haben)

Das Schlüsselkonzept hierbei ist, dass Methoden wie hasMoreThan() und transferTo() direkt auf den privaten Member balance eines anderen Wallet-Objekts zugreifen können — es sind keine Getter erforderlich. Dies funktioniert, weil die Zugriffskontrolle in C++ klassenbasiert ist: Jeder Code innerhalb der Klasse Wallet kann auf private Member jedes Wallet-Objekts zugreifen.

Formatieren Sie alle Geldwerte mit zwei Dezimalstellen unter Verwendung von std::fixed und std::setprecision(2) aus <iomanip>. Konvertieren Sie die Guthaben-Eingaben mit std::stod().

Spickzettel

Die Zugriffskontrolle in C++ wird auf Klassenebene erzwungen, nicht auf Objektebene. Das bedeutet, dass Objekte derselben Klasse auf die privaten Member der jeweils anderen zugreifen können:

class Person {
    std::string secret;
    
public:
    Person(std::string s) : secret(s) {}
    
    void readSecret(const Person& other) {
        // Zugriff auf das private Member eines anderen Objekts - erlaubt!
        std::cout << other.secret;
    }
};

Die Methode readSecret kann auf das private Member secret jedes Person-Objekts zugreifen, da sie Teil der Klasse Person ist. Dieses Design ermöglicht Operationen wie Kopierkonstruktoren und Vergleichsoperatoren.

Sie können innerhalb einer Klasse mehrmals zwischen Zugriffsspezifizierern wechseln:

class Mixed {
public:
    void publicMethod1();
    
private:
    int privateData;
    
public:
    void publicMethod2();    // Zurück zu public
    
private:
    void privateHelper();    // Wieder private
};

Es ist jedoch eine bessere Praxis, Member zur besseren Lesbarkeit nach Zugriffsebene zu gruppieren. Die meisten Styleguides empfehlen, zuerst öffentliche Member aufzuführen, gefolgt von geschützten und dann privaten.

Probier es selbst

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

using namespace std;

int main() {
    // Eingabe lesen: 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);
    
    // Ausgabeformatierung für Währungswerte festlegen
    cout << fixed << setprecision(2);
    
    // TODO: Zwei Wallet-Objekte mit den Eingabewerten erstellen
    
    // TODO: Gesamtes Vermögen mit combinedBalance() ausgeben
    // Format: "Combined wealth: $<amount>"
    
    // TODO: Wallets mit hasMoreThan() vergleichen und ausgeben, wer mehr Geld hat
    // Format: "<name> has more money"
    
    // TODO: 100.0 von der ersten Wallet auf die zweite mit transferTo() übertragen
    
    // TODO: "After transfer:" ausgeben
    
    // TODO: Gesamtes Vermögen erneut ausgeben
    
    // TODO: Erneut vergleichen und ausgeben, wer mehr Geld hat
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung