Especificadores de acceso en C++
Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 34 de 104.
C++ proporciona tres especificadores de acceso que controlan quién puede acceder a los miembros de la clase: public, protected y private. Estos forman la base de la encapsulación.
class Account {
public:
std::string ownerName; // Accesible desde cualquier lugar
protected:
double interestRate; // Accesible en esta clase y clases derivadas
private:
double balance; // Accesible solo dentro de esta clase
};Los miembros Public pueden ser accedidos desde cualquier lugar: dentro de la clase, desde clases derivadas y desde código externo. Los miembros Private son los más restrictivos, accesibles solo dentro de la propia clase. Protected se sitúa en un punto intermedio: actúa como privado para el mundo exterior, pero las clases derivadas pueden acceder a estos miembros.
class Account {
private:
double balance;
public:
Account() : balance(0) {}
void deposit(double amount) {
balance += amount; // OK - dentro de la clase
}
};
int main() {
Account acc;
acc.deposit(100); // OK - deposit es público
// acc.balance = 500; // ERROR - balance es privado
}Por defecto, todos los miembros en una class son private si no se proporciona ningún especificador. Esto le anima a decidir explícitamente qué debe ser expuesto. La práctica general es hacer que los miembros de datos sean private y proporcionar métodos public para interactuar con ellos de forma segura.
Desafío
FácilVamos a construir un sistema simple de gestión de empleados que demuestre cómo los especificadores de acceso controlan quién puede acceder a qué. Crearás una clase donde algunos datos son completamente privados, otros son accesibles para posibles subclases y otros están abiertos para todos.
Crearás dos archivos para organizar tu código:
Employee.h: Define una claseEmployeeque utiliza los tres especificadores de acceso para proteger los datos de manera adecuada:- Public: El
name(string) del empleado — se puede acceder desde cualquier lugar - Protected: El
department(string) del empleado — accesible dentro de la clase y por clases derivadas, pero no desde el exterior - Private: El
salary(double) del empleado — solo accesible dentro de la propia clase - Un constructor que recibe name, department y salary para inicializar los tres miembros
- Un método público
getSalary()que devuelve el valor privado del salario - Un método público
getDepartment()que devuelve el valor protegido del departamento - Un método público
giveRaise(double amount)que aumenta el salario en la cantidad dada (solo si la cantidad es positiva) - Un método público
displayInfo()que imprime la información del empleado en el formato:"Name: <name>, Department: <department>, Salary: "Name: <name>, Department: <department>, Salary: $<salary>"lt;salary>"
- Public: El
main.cpp: Demuestra cómo funcionan los especificadores de acceso interactuando con un objeto Employee. Lee el nombre, departamento y salario de un empleado desde la entrada (tres líneas separadas), luego:- Crea un
Employeecon los valores de entrada - Imprime el nombre del empleado directamente accediendo al miembro público:
"Direct access - Name: <name>" - Imprime el departamento usando el getter:
"Via getter - Department: <department>" - Imprime el salario usando el getter:
"Via getter - Salary: "Via getter - Salary: $<salary>"lt;salary>" - Dale al empleado un aumento de
5000.0 - Imprime
"After raise:" - Llama a
displayInfo()para mostrar la información actualizada
- Crea un
Formatea todos los valores de salario con dos decimales usando std::fixed y std::setprecision(2) de <iomanip>. Convierte la entrada del salario de string a double usando std::stod().
La idea clave aquí es que, si bien puedes acceder a name directamente desde main, no puedes acceder a department o salary directamente; debes usar los métodos getter públicos. Esto es la encapsulación en acción: la clase controla cómo se accede y se modifican sus datos.
Hoja de referencia
C++ proporciona tres especificadores de acceso para controlar el acceso a los miembros de la clase:
- public: Accesible desde cualquier lugar
- protected: Accesible dentro de la clase y en clases derivadas
- private: Accesible solo dentro de la propia clase
class Account {
public:
std::string ownerName; // Accessible from anywhere
protected:
double interestRate; // Accessible in this class and derived classes
private:
double balance; // Accessible only within this class
};Por defecto, todos los miembros de una clase son private si no se indica ningún especificador.
Ejemplo que demuestra el control de acceso:
class Account {
private:
double balance;
public:
Account() : balance(0) {}
void deposit(double amount) {
balance += amount; // OK - inside the class
}
};
int main() {
Account acc;
acc.deposit(100); // OK - deposit is public
// acc.balance = 500; // ERROR - balance is private
}Mejor práctica: Hacer que los miembros de datos sean privados y proporcionar métodos públicos para interactuar con ellos de forma segura.
Pruébalo tú mismo
#include <iostream>
#include <string>
#include <iomanip>
#include "Employee.h"
using namespace std;
int main() {
// Leer la entrada
string name;
string department;
string salaryStr;
getline(cin, name);
getline(cin, department);
getline(cin, salaryStr);
double salary = stod(salaryStr);
// Establecer la precisión para la salida del salario
cout << fixed << setprecision(2);
// TODO: Crear un objeto Employee con los valores de entrada
// TODO: Imprimir el nombre del empleado accediendo directamente al miembro público
// Formato: "Direct access - Name: <name>"
// TODO: Imprimir el departamento usando el método getter
// Formato: "Via getter - Department: <department>"
// TODO: Imprimir el salario usando el método getter
// Formato: "Via getter - Salary: $<salary>"
// TODO: Dar al empleado un aumento de 5000.0
// TODO: Imprimir "After raise:"
// TODO: Llamar a displayInfo() para mostrar la información actualizada
return 0;
}
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
1Fundamentos de OOP
Archivos externosConstrucción y compilación en C++Archivos de cabecera y archivos fuenteNamespaces y alcanceIntroducción a OOP en C++Clases vs ObjetosEl puntero 'this'Métodos (Funciones miembro)Atributos (Miembros de datos)Conceptos básicos de Ctors y DtorsResumen - Calculadora simple4Propiedades de clase
Miembros de instancia vs. estáticosGetters y SettersFunciones miembro constPalabra clave mutableMétodos y variables estáticosFunciones y clases amigasResumen - Gestor de cuentas bancarias7Herencia
Herencia básicaNiveles de acceso en la herenciaOrden de llamada de Ctor y DtorSobrescritura de métodosFunciones virtuales y VTableHerencia múltipleHerencia virtualResumen - Jerarquía de empleados2Gestión de memoria
Memoria Stack vs HeapPunteros y referenciasMemoria dinámica (new/delete)Punteros inteligentes en C++RAII en C++Resumen - Gestor de arrays dinámicos5Encapsulamiento
Especificadores de acceso en C++Especificadores de acceso en profundidadOcultamiento de informaciónStruct vs ClassClases anidadas e internasResumen - Sistema de registros de estudiantes8Polimorfismo
Polimorfismo: Compilación vs. Tiempo de ejecuciónSobrecarga de funcionesFunciones virtuales revisadasFunciones virtuales purasClases abstractasDiseño de interfaces en C++Dynamic Casting y RTTIResumen: Calculadora de figuras11Conceptos avanzados de POO
Composición vs. HerenciaMixins mediante CRTPIdioma PimplBorrado de tiposEnum Classes y tipado fuerteManejo de excepciones en POOJerarquías de excepciones personalizadas14Patrones de diseño - Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositeRAII como patrón3Constructores y Destructores
Constructor por defectoConstructor parametrizadoConstructor de copiaConstructor de movimientoListas de inicialización del constructorConstructores delegadosAnálisis profundo del destructorRegla de tres / cinco / ceroResumen - Clase String6Sobrecarga de operadores
Introducción a la sobrecarga de operadoresSobrecarga de operadores aritméticosSobrecarga de operadores de comparaciónOperadores de flujo (Stream)Sobrecarga del operador de asignaciónSobrecarga de los operadores [] y ()Operadores de conversión de tiposResumen - Clase Matrix9Plantillas
Plantillas de funcionesPlantillas de clasesEspecialización de plantillasPlantillas variádicasConceptos básicos de SFINAE y Type TraitsResumen - Contenedor genérico