Menu
Coddy logo textTech

Zugriffsbezeichner im Detail

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

Nachdem du nun die drei Zugriffsbezeichner verstanden hast, wollen wir untersuchen, wie sie sich verhalten, wenn du mehrere Objekte derselben Klasse hast. Ein häufiges Missverständnis besteht darin, dass private „nur dieses Objekt“ bedeutet – tatsächlich bedeutet es jedoch „nur diese Klasse“.

Objekte derselben Klasse können auf die privaten Member des 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;
    }
};

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

Du kannst auch innerhalb einer Klasse mehrmals zwischen Zugriffsbezeichnern 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 zur besseren Lesbarkeit nach Zugriffsebene zu gruppieren. Die meisten Styleguides empfehlen, öffentliche Member zuerst aufzulisten (da sie die Klassenschnittstelle bilden), gefolgt von geschützten und dann privaten Membern.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Wallet-Vergleichssystem, das veranschaulicht, wie Objekte derselben Klasse auf die privaten Member der jeweils anderen Objekte zugreifen können. Dies ist eine wichtige Erkenntnis über die Zugriffskontrolle in C++: Sie wird auf Klassenebene durchgesetzt, nicht auf Objektebene.

Du erstellst zwei Dateien, um deinen Code zu organisieren:

  • Wallet.h: Definiere eine Wallet-Klasse, die private Finanzdaten speichert, aber Vergleiche zwischen Wallets ermöglicht. Deine Klasse sollte Folgendes enthalten:
    • Private Member: ownerName (String) und balance (Double)
    • Einen Konstruktor, der den Namen des Eigentümers und das Anfangsguthaben entgegennimmt
    • Einen öffentlichen Getter getOwnerName(), der den Namen des Eigentümers 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: Veranschauliche den objektübergreifenden Zugriff auf private Member. Lies zwei Eigentümernamen und zwei Guthaben aus der Eingabe ein (vier Zeilen: name1, balance1, name2, balance2), und führe dann Folgendes aus:
    • Erstelle zwei Wallet-Objekte mit den Eingabewerten
    • Gib "Combined wealth: $<amount>" mithilfe von combinedBalance() aus
    • Vergleiche die Wallets und gib für den Eigentümer mit dem höheren Guthaben "<name> has more money" aus (verwende hasMoreThan(), um dies zu bestimmen)
    • Übertrage mit 100.0 transferTo() vom ersten Wallet auf das zweite
    • Gib "After transfer:" aus
    • Gib erneut "Combined wealth: $<amount>" aus (sollte unverändert sein)
    • Vergleiche erneut und gib "<name> has more money" aus (das Ergebnis kann sich geändert haben)

Das zentrale Konzept hierbei ist, dass Methoden wie hasMoreThan() und transferTo() direkt auf das private Wallet-Member eines anderen balance-Objekts zugreifen können: Getter sind nicht erforderlich. Dies funktioniert, weil die Zugriffskontrolle in C++ klassenbasiert ist: Jeder Code innerhalb der Wallet-Klasse kann auf private Member von jedem Wallet-Objekt zugreifen.

Formatiere alle Geldbeträge mit zwei Dezimalstellen mithilfe von std::fixed und std::setprecision(2) aus <iomanip>. Konvertiere die Guthabeneingaben mithilfe von std::stod().

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 Geldbeträge festlegen
    cout << fixed << setprecision(2);
    
    // TODO: Erstelle zwei Wallet-Objekte mit den Eingabewerten
    
    // TODO: Print combined wealth using combinedBalance()
    // Format: "Combined wealth: $<amount>"
    
    // TODO: Compare wallets using hasMoreThan() and print who has more money
    // Format: "<name> has more money"
    
    // TODO: Überweise 100.0 vom ersten Wallet zum zweiten mit transferTo()
    
    // TODO: Print "After transfer:"
    
    // TODO: Print combined wealth again
    
    // TODO: Compare again and print who has more money
    
    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

Übe selbstständig: Online-C++-Compiler