Menu
Coddy logo textTech

Friend-Funktionen & Klassen

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

Manchmal benötigt eine Funktion oder Klasse außerhalb Ihrer Klasse Zugriff auf deren private Member. Anstatt diese Member öffentlich zu machen, bietet C++ das Schlüsselwort friend an, um selektiven Zugriff zu gewähren und gleichzeitig die Kapselung beizubehalten.

Eine Friend-Funktion wird innerhalb einer Klasse deklariert, ist aber kein Element dieser Klasse. Sie kann auf die privaten und geschützten Elemente der Klasse zugreifen:

class Box {
    double width;
    
public:
    Box(double w) : width(w) {}
    
    // Deklariere printWidth als Friend
    friend void printWidth(const Box& b);
};

// Definition der Friend-Funktion - KEINE Member-Funktion
void printWidth(const Box& b) {
    std::cout << b.width;    // Kann auf private Member zugreifen
}

Beachten Sie, dass printWidth außerhalb der Klasse ohne den Bereichsauflösungsoperator definiert ist. Es handelt sich um eine reguläre Funktion, die zufällig über spezielle Zugriffsberechtigungen verfügt.

Sie können auch eine gesamte Klasse als Friend deklarieren, wodurch alle ihre Elementfunktionen Zugriff auf private Member erhalten:

class Engine {
    int horsepower;
    
    friend class Mechanic;    // Mechanic kann auf private Member zugreifen
    
public:
    Engine(int hp) : horsepower(hp) {}
};

class Mechanic {
public:
    void diagnose(const Engine& e) {
        std::cout << e.horsepower;    // Erlaubt - Mechanic ist ein Freund
    }
};

Freundschaft ist nicht wechselseitig – wenn Engine die Klasse Mechanic als Freund deklariert, kann Mechanic auf die privaten Member von Engine zugreifen, aber nicht umgekehrt. Verwenden Sie Freunde sparsam, da sie eine enge Kopplung zwischen Klassen erzeugen. Sie sind am nützlichsten für die Operatorüberladung und eng verwandte Hilfsfunktionen.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein sicheres Nachrichtensystem bauen, bei dem eine MessageReader-Klasse speziellen Zugriff benötigt, um verschlüsselte Nachrichten zu lesen, die in einer SecureMessage-Klasse gespeichert sind. Dies ist ein perfektes Szenario für die Verwendung von Friend-Funktionen und Friend-Klassen.

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

  • SecureMessage.h: Definieren Sie eine SecureMessage-Klasse, die private Nachrichtendaten speichert und vertrauenswürdigen Entitäten selektiven Zugriff gewährt. Ihre Klasse sollte Folgendes haben:
    • Private Member: content (string) und secretKey (int)
    • Einen Konstruktor, der den Inhalt und den geheimen Schlüssel entgegennimmt
    • Deklarieren Sie MessageReader als Friend-Klasse, damit sie auf private Member zugreifen kann
    • Deklarieren Sie eine Friend-Funktion decryptMessage(const SecureMessage& msg, int key), die den Inhalt nur zurückgibt, wenn der angegebene Schlüssel mit dem geheimen Schlüssel übereinstimmt, andernfalls "Access Denied" zurückgibt

    Definieren Sie dann die MessageReader-Klasse in derselben Header-Datei:

    • Eine Methode readContent(const SecureMessage& msg), die direkt auf den privaten content der Nachricht zugreift und diesen zurückgibt
    • Eine Methode verifyKey(const SecureMessage& msg, int key), die prüft, ob der angegebene Schlüssel mit dem secretKey der Nachricht übereinstimmt, und "Valid" oder "Invalid" zurückgibt

    Definieren Sie schließlich die Friend-Funktion decryptMessage nach den Klassen.

  • main.cpp: Demonstrieren Sie sowohl Friend-Funktionen als auch Friend-Klassen in Aktion. Lesen Sie einen Nachrichteninhalt, einen geheimen Schlüssel und einen Testschlüssel von der Eingabe (jeweils in einer separaten Zeile) und führen Sie dann Folgendes aus:
    • Erstellen Sie eine SecureMessage mit dem Inhalt und dem geheimen Schlüssel
    • Erstellen Sie ein MessageReader-Objekt
    • Geben Sie "Reader access: <content>" unter Verwendung der readContent()-Methode des Readers aus
    • Geben Sie "Key verification: <result>" unter Verwendung von verifyKey() mit dem Testschlüssel aus
    • Geben Sie "Decrypt with test key: <result>" unter Verwendung der Friend-Funktion mit dem Testschlüssel aus
    • Geben Sie "Decrypt with correct key: <result>" unter Verwendung der Friend-Funktion mit dem ursprünglichen geheimen Schlüssel aus

Denken Sie daran, dass Friend-Funktionen außerhalb der Klasse ohne den Bereichsauflösungsoperator definiert werden — es sind reguläre Funktionen mit speziellen Zugriffsberechtigungen. Die MessageReader-Klasse kann als Friend in all ihren Methoden direkt auf die privaten Member von SecureMessage zugreifen.

Konvertieren Sie die Schlüsseleingaben mit std::stoi() von Strings in Integer. Binden Sie Ihre Header-Datei in main.cpp mit #include "SecureMessage.h" ein.

Spickzettel

Das Schlüsselwort friend gewährt selektiven Zugriff auf private Member, während die Kapselung beibehalten wird.

Friend-Funktion: Eine innerhalb einer Klasse deklarierte Funktion, die auf deren private und geschützte Member zugreifen kann, aber kein Member der Klasse ist:

class Box {
    double width;
    
public:
    Box(double w) : width(w) {}
    
    // Friend-Funktion deklarieren
    friend void printWidth(const Box& b);
};

// Außerhalb der Klasse ohne Bereichsauflösungsoperator definieren
void printWidth(const Box& b) {
    std::cout << b.width;    // Kann auf privaten Member zugreifen
}

Friend-Klasse: Eine gesamte Klasse kann als Friend deklariert werden, wodurch alle ihre Member-Funktionen Zugriff auf private Member erhalten:

class Engine {
    int horsepower;
    
    friend class Mechanic;    // Alle Mechanic-Methoden können auf private Member zugreifen
    
public:
    Engine(int hp) : horsepower(hp) {}
};

class Mechanic {
public:
    void diagnose(const Engine& e) {
        std::cout << e.horsepower;    // Erlaubt
    }
};

Wichtige Punkte:

  • Freundschaft ist nicht wechselseitig – wenn A B als Friend deklariert, kann B auf die privaten Member von A zugreifen, aber nicht umgekehrt
  • Friend-Funktionen werden außerhalb der Klasse ohne den Bereichsauflösungsoperator definiert
  • Verwenden Sie Friends sparsam, da sie eine enge Kopplung zwischen Klassen erzeugen
  • Am nützlichsten für Operatorüberladung und eng verwandte Hilfsfunktionen

Probier es selbst

#include <iostream>
#include <string>
#include "SecureMessage.h"
using namespace std;

int main() {
    // Eingabe lesen
    string messageContent;
    string secretKeyStr;
    string testKeyStr;
    
    getline(cin, messageContent);
    getline(cin, secretKeyStr);
    getline(cin, testKeyStr);
    
    int secretKey = stoi(secretKeyStr);
    int testKey = stoi(testKeyStr);
    
    // TODO: Erstelle eine SecureMessage mit dem Inhalt und dem geheimen Schlüssel (secret key)
    
    // TODO: Erstelle ein MessageReader-Objekt
    
    // TODO: Gib "Reader access: <content>" unter Verwendung von readContent() aus
    
    // TODO: Gib "Key verification: <result>" unter Verwendung von verifyKey() mit dem Test-Schlüssel (test key) aus
    
    // TODO: Gib "Decrypt with test key: <result>" unter Verwendung von decryptMessage mit dem Test-Schlüssel (test key) aus
    
    // TODO: Gib "Decrypt with correct key: <result>" unter Verwendung von decryptMessage mit dem geheimen Schlüssel (secret key) aus
    
    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