Menu
Coddy logo textTech

Funções e Classes Friend

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy. Lição 32 de 104.

Às vezes, uma função ou classe externa à sua classe precisa acessar seus membros privados. Em vez de tornar esses membros públicos, o C++ fornece a palavra-chave friend para conceder acesso seletivo mantendo o encapsulamento.

Uma função friend é declarada dentro de uma classe, mas não é membro dessa classe. Ela pode acessar os membros privados e protegidos da classe:

class Box {
    double width;
    
public:
    Box(double w) : width(w) {}
    
    // Declare printWidth como friend
    friend void printWidth(const Box& b);
};

// Definição de função friend - NÃO é uma função membro
void printWidth(const Box& b) {
    std::cout << b.width;    // Pode acessar membro privado
}

Observe que printWidth é definido fora da classe sem o operador de resolução de escopo. É uma função comum que, por acaso, tem privilégios de acesso especiais.

Você também pode tornar uma classe inteira uma amiga, concedendo a todas as suas funções membro acesso aos membros privados:

class Engine {
    int horsepower;
    
    friend class Mechanic;    // Mechanic pode acessar membros privados
    
public:
    Engine(int hp) : horsepower(hp) {}
};

class Mechanic {
public:
    void diagnose(const Engine& e) {
        std::cout << e.horsepower;    // Permitido - Mechanic é um friend
    }
};

A amizade não é mútua — se Engine declara Mechanic como amigo, Mechanic pode acessar os members privados de Engine, mas o contrário não é válido. Use amigos com moderação, pois eles criam um forte acoplamento entre as classes. Eles são mais úteis para sobrecarga de operator e funções auxiliares estreitamente relacionadas.

challenge icon

Desafio

Fácil

Vamos criar um sistema de mensagens seguro em que uma classe MessageReader precisa de acesso especial para ler mensagens criptografadas armazenadas em uma classe SecureMessage. Este é um cenário perfeito para usar funções amigas e classes amigas.

Você criará dois arquivos para organizar seu código:

  • SecureMessage.h: Defina uma classe SecureMessage que armazene dados privados da mensagem e conceda acesso seletivo a entidades confiáveis. Sua classe deve ter:
    • Membros privados: content (string) e secretKey (int)
    • Um construtor que receba o conteúdo e a chave secreta
    • Declare MessageReader como uma classe amiga para que ela possa acessar os membros privados
    • Declare uma função amiga decryptMessage(const SecureMessage& msg, int key) que retorne o conteúdo somente se a chave fornecida corresponder à chave secreta; caso contrário, retorne "Access Denied"

    Em seguida, defina a classe MessageReader no mesmo arquivo de cabeçalho:

    • Um método readContent(const SecureMessage& msg) que acesse diretamente e retorne o content privado da mensagem
    • Um método verifyKey(const SecureMessage& msg, int key) que verifique se a chave fornecida corresponde à secretKey da mensagem e retorne "Valid" ou "Invalid"

    Por fim, defina a função amiga decryptMessage após as classes.

  • main.cpp: Demonstre as funções amigas e as classes amigas em ação. Leia o conteúdo de uma mensagem, uma chave secreta e uma chave de teste da entrada (cada um em uma linha separada) e, em seguida:
    • Crie uma SecureMessage com o conteúdo e a chave secreta
    • Crie um objeto MessageReader
    • Imprima "Reader access: <content>" usando o método readContent() do leitor
    • Imprima "Key verification: <result>" usando verifyKey() com a chave de teste
    • Imprima "Decrypt with test key: <result>" usando a função amiga com a chave de teste
    • Imprima "Decrypt with correct key: <result>" usando a função amiga com a chave secreta original

Lembre-se de que as funções amigas são definidas fora da classe sem o operador de resolução de escopo: elas são funções comuns com privilégios especiais de acesso. A classe MessageReader, por ser amiga, pode acessar diretamente os membros privados de SecureMessage em todos os seus métodos.

Converta as entradas de chave de strings para inteiros usando std::stoi(). Inclua seu arquivo de cabeçalho em main.cpp usando #include "SecureMessage.h".

Experimente você mesmo

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

int main() {
    // Ler 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: Crie um SecureMessage com o conteúdo e a chave secreta
    
    // TODO: Crie um objeto MessageReader
    
    // TODO: Print "Reader access: <content>" using readContent()
    
    // TODO: Print "Key verification: <result>" using verifyKey() with test key
    
    // TODO: Print "Decrypt with test key: <result>" using decryptMessage with test key
    
    // TODO: Print "Decrypt with correct key: <result>" using decryptMessage with secret key
    
    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de C++ online