Menu
Coddy logo textTech

Especificadores de Acesso em Detalhes

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 35 de 104.

Agora que você entende os três especificadores de acesso, vamos explorar como eles se comportam quando você tem múltiplos objetos da mesma classe. Um equívoco comum é que private significa "apenas este objeto" - mas, na verdade, significa "apenas esta classe".

Objetos da mesma classe podem acessar os membros privados uns dos outros:

class Person {
    std::string secret;
    
public:
    Person(std::string s) : secret(s) {}
    
    void readSecret(const Person& other) {
        // Acessando o membro privado de outro objeto - permitido!
        std::cout << other.secret;
    }
};

Isso funciona porque o controle de acesso é aplicado no nível da classe, não no nível do objeto. O método readSecret faz parte da classe Person, portanto, ele pode acessar membros privados de qualquer objeto Person. Esse design permite que operações como construtores de cópia e operadores de comparação trabalhem com o estado interno de outros objetos.

Você também pode alternar entre especificadores de acesso várias vezes dentro de uma classe:

class Mixed {
public:
    void publicMethod1();
    
private:
    int privateData;
    
public:
    void publicMethod2();    // De volta para public
    
private:
    void privateHelper();    // Privado novamente
};

Embora isso seja C++ válido, geralmente é melhor agrupar os membros por nível de acesso para fins de legibilidade. A maioria dos guias de estilo recomenda listar os membros públicos primeiro (já que eles formam a interface da classe), seguidos pelos protegidos e, depois, pelos privados.

challenge icon

Desafio

Fácil

Vamos construir um sistema de comparação de carteiras que demonstra como objetos da mesma classe podem acessar os membros privados uns dos outros. Este é um insight fundamental sobre o controle de acesso em C++ — ele é aplicado no nível da classe, não no nível do objeto.

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

  • Wallet.h: Defina uma classe Wallet que armazena dados financeiros privados, mas permite comparações entre carteiras. Sua classe deve ter:
    • Membros privados: ownerName (string) e balance (double)
    • Um construtor que recebe o nome do proprietário e o saldo inicial
    • Um getter público getOwnerName() que retorna o nome do proprietário
    • Um método hasMoreThan(const Wallet& other) que compara o saldo desta carteira com o saldo privado de outra carteira, retornando true se esta carteira tiver mais dinheiro
    • Um método combinedBalance(const Wallet& other) que retorna a soma dos saldos privados de ambas as carteiras
    • Um método transferTo(Wallet& other, double amount) que move dinheiro desta carteira para outra — ele deve modificar diretamente os saldos privados de ambas as carteiras (apenas se o valor for positivo e não exceder o saldo desta carteira)
  • main.cpp: Demonstre o acesso a membros privados entre objetos. Leia dois nomes de proprietários e dois saldos da entrada (quatro linhas: name1, balance1, name2, balance2) e, em seguida:
    • Crie dois objetos Wallet com os valores de entrada
    • Imprima "Combined wealth: "Combined wealth: $"lt;amount>" usando combinedBalance()
    • Compare as carteiras e imprima "<name> has more money" para o proprietário que tiver o saldo maior (use hasMoreThan() para determinar isso)
    • Transfira 100.0 da primeira carteira para a segunda usando transferTo()
    • Imprima "After transfer:"
    • Imprima "Combined wealth: "Combined wealth: $"lt;amount>" novamente (deve permanecer inalterado)
    • Compare novamente e imprima "<name> has more money" (o resultado pode ter mudado)

O conceito principal aqui é que métodos como hasMoreThan() e transferTo() podem acessar diretamente o membro privado balance de outro objeto Wallet — sem a necessidade de getters. Isso funciona porque o controle de acesso em C++ é baseado em classe: qualquer código dentro da classe Wallet pode acessar membros privados de qualquer objeto Wallet.

Formate todos os valores monetários com duas casas decimais usando std::fixed e std::setprecision(2) de <iomanip>. Converta as entradas de saldo usando std::stod().

Folha de consulta

O controle de acesso em C++ é aplicado no nível da classe, não no nível do objeto. Isso significa que objetos da mesma classe podem acessar os membros privados uns dos outros:

class Person {
    std::string secret;
    
public:
    Person(std::string s) : secret(s) {}
    
    void readSecret(const Person& other) {
        // Acessando o membro privado de outro objeto - permitido!
        std::cout << other.secret;
    }
};

O método readSecret pode acessar o membro privado secret de qualquer objeto Person porque ele faz parte da classe Person. Esse design permite operações como construtores de cópia e operadores de comparação.

Você pode alternar entre especificadores de acesso várias vezes dentro de uma classe:

class Mixed {
public:
    void publicMethod1();
    
private:
    int privateData;
    
public:
    void publicMethod2();    // De volta para public
    
private:
    void privateHelper();    // Privado novamente
};

No entanto, é uma prática melhor agrupar os membros por nível de acesso para facilitar a leitura. A maioria dos guias de estilo recomenda listar os membros públicos primeiro, seguidos pelos protegidos e, depois, pelos privados.

Experimente você mesmo

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

using namespace std;

int main() {
    // Ler entrada: 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);
    
    // Configurar a formatação de saída para valores monetários
    cout << fixed << setprecision(2);
    
    // TODO: Criar dois objetos Wallet com os valores de entrada
    
    // TODO: Imprimir a riqueza combinada usando combinedBalance()
    // Formato: "Combined wealth: $<amount>"
    
    // TODO: Comparar as carteiras usando hasMoreThan() e imprimir quem tem mais dinheiro
    // Formato: "<name> has more money"
    
    // TODO: Transferir 100.0 da primeira carteira para a segunda usando transferTo()
    
    // TODO: Imprimir "After transfer:"
    
    // TODO: Imprimir a riqueza combinada novamente
    
    // TODO: Comparar novamente e imprimir quem tem mais dinheiro
    
    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