Menu
Coddy logo textTech

Especificadores de acceso en profundidad

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 35 de 104.

Ahora que entiendes los tres especificadores de acceso, exploremos cómo se comportan cuando tienes varios objetos de la misma clase. Un error común es pensar que private significa «solo este objeto», pero en realidad significa «solo esta clase».

Los objetos de la misma clase pueden acceder a los miembros privados de los demás:

class Person {
    std::string secret;
    
public:
    Person(std::string s) : secret(s) {}
    
    void readSecret(const Person& other) {
        // Accediendo al miembro privado de otro objeto - ¡permitido!
        std::cout << other.secret;
    }
};

Esto funciona porque el control de acceso se aplica en el nivel de clase, no en el nivel de objeto. El método readSecret forma parte de la clase Person, por lo que puede acceder a los miembros privados de cualquier objeto Person. Este diseño permite que operaciones como los constructores de copia y los operadores de comparación funcionen con el estado interno de otros objetos.

También puedes alternar entre los especificadores de acceso varias veces dentro de una clase:

class Mixed {
public:
    void publicMethod1();
    
private:
    int privateData;
    
public:
    void publicMethod2();    // De vuelta a público
    
private:
    void privateHelper();    // Privado de nuevo
};

Aunque esto es C++ válido, generalmente es mejor agrupar los miembros por nivel de acceso para facilitar la legibilidad. La mayoría de las guías de estilo recomiendan enumerar primero los miembros públicos (ya que forman la interfaz de la clase), seguidos de los protegidos y después los privados.

challenge icon

Desafío

Fácil

Construyamos un sistema de comparación de billeteras que demuestre cómo los objetos de la misma clase pueden acceder a los miembros privados de los demás. Esta es una idea clave sobre el control de acceso de C++: se aplica a nivel de clase, no a nivel de objeto.

Crearás dos archivos para organizar tu código:

  • Wallet.h: Define una clase Wallet que almacena datos financieros privados, pero permite las comparaciones entre billeteras. Tu clase debe tener:
    • Miembros privados: ownerName (cadena) y balance (double)
    • Un constructor que reciba el nombre del propietario y el saldo inicial
    • Un getter público getOwnerName() que devuelva el nombre del propietario
    • Un método hasMoreThan(const Wallet& other) que compare el saldo de esta billetera con el saldo privado de otra billetera y devuelva true si esta billetera tiene más dinero
    • Un método combinedBalance(const Wallet& other) que devuelva la suma de los saldos privados de ambas billeteras
    • Un método transferTo(Wallet& other, double amount) que transfiera dinero de esta billetera a otra. Debe modificar directamente los saldos privados de ambas billeteras (solo si amount es positivo y no supera el saldo de esta billetera)
  • main.cpp: Demuestra el acceso a miembros privados entre objetos. Lee dos nombres de propietarios y dos saldos de la entrada (cuatro líneas: name1, balance1, name2, balance2), después:
    • Crea dos objetos Wallet con los valores introducidos
    • Imprime "Combined wealth: $<amount>" usando combinedBalance()
    • Compara las billeteras e imprime "<name> has more money" para el propietario cuyo saldo sea mayor (usa hasMoreThan() para determinarlo)
    • Transfiere 100.0 de la primera billetera a la segunda usando transferTo()
    • Imprime "After transfer:"
    • Vuelve a imprimir "Combined wealth: $<amount>" (debería mantenerse sin cambios)
    • Vuelve a comparar e imprime "<name> has more money" (el resultado puede haber cambiado)

El concepto clave aquí es que métodos como hasMoreThan() y transferTo() pueden acceder directamente al miembro privado Wallet de otro objeto balance: no se necesitan getters. Esto funciona porque el control de acceso en C++ se basa en la clase: cualquier código dentro de la clase Wallet puede acceder a los miembros privados de cualquier objeto Wallet.

Da formato a todos los valores monetarios con dos posiciones decimales usando std::fixed y std::setprecision(2) de <iomanip>. Convierte las entradas de saldo usando std::stod().

Pruébalo tú mismo

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

using namespace std;

int main() {
    // Leer 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);
    
    // Establecer el formato de salida para valores monetarios
    cout << fixed << setprecision(2);
    
    // TODO: Crear dos objetos Wallet con los valores de entrada
    
    // 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: Transferir 100.0 de la primera billetera a la segunda usando transferTo()
    
    // TODO: Print "After transfer:"
    
    // TODO: Print combined wealth again
    
    // TODO: Compare again and print who has more money
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C++ online