Menu
Coddy logo textTech

Funzioni e classi friend

Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 32 di 104.

A volte una funzione o una classe esterna alla tua classe ha bisogno di accedere ai suoi membri privati. Invece di rendere pubblici quei membri, C++ fornisce la parola chiave friend per concedere un accesso selettivo mantenendo l'incapsulamento.

Una funzione friend è dichiarata all'interno di una classe, ma non è un membro di quella classe. Può accedere ai membri privati e protetti della classe:

class Box {
    double width;
    
public:
    Box(double w) : width(w) {}
    
    // Dichiara printWidth come funzione friend
    friend void printWidth(const Box& b);
};

// Definizione della funzione friend - NON è una funzione membro
void printWidth(const Box& b) {
    std::cout << b.width;    // Può accedere al membro privato
}

Nota che printWidth è definita al di fuori della classe senza l'operatore di risoluzione dell'ambito. È una funzione normale che, per caso, dispone di privilegi di accesso speciali.

Puoi anche rendere amica un'intera classe, concedendo a tutte le sue funzioni membro l'accesso ai membri privati:

class Engine {
    int horsepower;
    
    friend class Mechanic;    // Mechanic può accedere ai membri privati
    
public:
    Engine(int hp) : horsepower(hp) {}
};

class Mechanic {
public:
    void diagnose(const Engine& e) {
        std::cout << e.horsepower;    // Consentito - Mechanic è una classe friend
    }
};

L'amicizia non è reciproca: se Engine dichiara Mechanic come amico, Mechanic può accedere ai membri privati di Engine, ma non viceversa. Usa gli amici con parsimonia, perché creano un forte accoppiamento tra le classi. Sono più utili per l'overloading degli operatori e per le funzioni helper strettamente correlate.

challenge icon

Sfida

Facile

Costruiamo un sistema di messaggistica sicuro in cui una classe MessageReader deve avere accesso speciale per leggere i messaggi crittografati memorizzati in una classe SecureMessage. Questo è uno scenario perfetto per usare funzioni amiche e classi amiche.

Creerai due file per organizzare il codice:

  • SecureMessage.h: definisci una classe SecureMessage che memorizza i dati privati del messaggio e concede accesso selettivo alle entità fidate. La tua classe dovrebbe avere:
    • Membri privati: content (stringa) e secretKey (int)
    • Un costruttore che accetta il contenuto e la chiave segreta
    • Dichiara MessageReader come classe amica affinché possa accedere ai membri privati
    • Dichiara una funzione amica decryptMessage(const SecureMessage& msg, int key) che restituisce il contenuto solo se la chiave fornita corrisponde alla chiave segreta; altrimenti restituisce "Access Denied"

    Definisci poi la classe MessageReader nello stesso file header:

    • Un metodo readContent(const SecureMessage& msg) che accede direttamente al membro privato content del messaggio e lo restituisce
    • Un metodo verifyKey(const SecureMessage& msg, int key) che verifica se la chiave fornita corrisponde a secretKey del messaggio e restituisce "Valid" oppure "Invalid"

    Infine, definisci la funzione amica decryptMessage dopo le classi.

  • main.cpp: mostra in azione sia le funzioni amiche sia le classi amiche. Leggi da input il contenuto di un messaggio, una chiave segreta e una chiave di prova (ciascuno su una riga separata), quindi:
    • Crea un oggetto SecureMessage con il contenuto e la chiave segreta
    • Crea un oggetto MessageReader
    • Stampa "Reader access: <content>" usando il metodo readContent() del lettore
    • Stampa "Key verification: <result>" usando verifyKey() con la chiave di prova
    • Stampa "Decrypt with test key: <result>" usando la funzione amica con la chiave di prova
    • Stampa "Decrypt with correct key: <result>" usando la funzione amica con la chiave segreta originale

Ricorda che le funzioni amiche vengono definite fuori dalla classe senza l'operatore di risoluzione dell'ambito: sono funzioni normali con privilegi di accesso speciali. La classe MessageReader, in quanto amica, può accedere direttamente ai membri privati di SecureMessage in tutti i suoi metodi.

Converti gli input delle chiavi da stringhe a interi usando std::stoi(). Includi il tuo file header in main.cpp usando #include "SecureMessage.h".

Provalo tu

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

int main() {
    // Lee la entrada
    string messageContent;
    string secretKeyStr;
    string testKeyStr;
    
    getline(cin, messageContent);
    getline(cin, secretKeyStr);
    getline(cin, testKeyStr);
    
    int secretKey = stoi(secretKeyStr);
    int testKey = stoi(testKeyStr);
    
    // TODO: Crea un SecureMessage con el contenido y la clave secreta
    
    // TODO: Crea un objeto MessageReader
    
    // TODO: Imprime "Reader access: <content>" usando readContent()
    
    // TODO: Imprime "Key verification: <result>" usando verifyKey() con la clave de prueba
    
    // TODO: Imprime "Decrypt with test key: <result>" usando decryptMessage con la clave de prueba
    
    // TODO: Imprime "Decrypt with correct key: <result>" usando decryptMessage con la clave secreta
    
    return 0;
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C++ online