Especificadores de Acesso em C++
Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 34 de 104.
O C++ fornece três especificadores de acesso que controlam quem pode acessar os membros da classe: public, protected e private. Eles formam a base do encapsulamento.
class Account {
public:
std::string ownerName; // Acessível de qualquer lugar
protected:
double interestRate; // Acessível nesta classe e em classes derivadas
private:
double balance; // Acessível apenas dentro desta classe
};Membros públicos podem ser acessados de qualquer lugar - dentro da classe, a partir de classes derivadas e de código externo. Membros privados são os mais restritivos, acessíveis apenas dentro da própria classe. Protegidos ficam no meio termo - eles agem como privados para o mundo externo, mas classes derivadas podem acessar esses membros.
class Account {
private:
double balance;
public:
Account() : balance(0) {}
void deposit(double amount) {
balance += amount; // OK - dentro da classe
}
};
int main() {
Account acc;
acc.deposit(100); // OK - deposit é público
// acc.balance = 500; // ERRO - balance é privado
}Por padrão, todos os membros em uma class são private se nenhum especificador for fornecido. Isso incentiva você a decidir explicitamente o que deve ser exposto. A prática geral é tornar os membros de dados private e fornecer métodos public para interagir com eles de forma segura.
Desafio
FácilVamos construir um sistema simples de gerenciamento de funcionários que demonstra como os especificadores de acesso controlam quem pode acessar o quê. Você criará uma classe onde alguns dados são completamente privados, alguns são acessíveis a potenciais subclasses e outros estão abertos a todos.
Você criará dois arquivos para organizar seu código:
Employee.h: Defina uma classeEmployeeque usa todos os três especificadores de acesso para proteger os dados adequadamente:- Public: O
name(string) do funcionário — este pode ser acessado de qualquer lugar - Protected: O
department(string) do funcionário — acessível dentro da classe e por classes derivadas, mas não de fora - Private: O
salary(double) do funcionário — acessível apenas dentro da própria classe - Um construtor que recebe name, department e salary para inicializar os três membros
- Um método público
getSalary()que retorna o valor privado do salário - Um método público
getDepartment()que retorna o valor protegido do departamento - Um método público
giveRaise(double amount)que aumenta o salário pelo valor fornecido (apenas se o valor for positivo) - Um método público
displayInfo()que imprime as informações do funcionário no formato:"Name: <name>, Department: <department>, Salary: "Name: <name>, Department: <department>, Salary: $<salary>"lt;salary>"
- Public: O
main.cpp: Demonstre como os especificadores de acesso funcionam interagindo com um objeto Employee. Leia o nome, departamento e salário de um funcionário a partir da entrada (três linhas separadas) e, em seguida:- Crie um
Employeecom os valores de entrada - Imprima o nome do funcionário diretamente acessando o membro público:
"Direct access - Name: <name>" - Imprima o departamento usando o getter:
"Via getter - Department: <department>" - Imprima o salário usando o getter:
"Via getter - Salary: "Via getter - Salary: $<salary>"lt;salary>" - Dê ao funcionário um aumento de
5000.0 - Imprima
"After raise:" - Chame
displayInfo()para mostrar as informações atualizadas
- Crie um
Formate todos os valores de salário com duas casas decimais usando std::fixed e std::setprecision(2) de <iomanip>. Converta a entrada do salário de string para double usando std::stod().
O ponto principal aqui é que, embora você possa acessar name diretamente do main, você não pode acessar department ou salary diretamente — você deve usar os métodos getter públicos. Isso é o encapsulamento em ação: a classe controla como seus dados são acessados e modificados.
Folha de consulta
O C++ fornece três especificadores de acesso para controlar o acesso aos membros da classe:
- public: Acessível de qualquer lugar
- protected: Acessível dentro da classe e classes derivadas
- private: Acessível apenas dentro da própria classe
class Account {
public:
std::string ownerName; // Acessível de qualquer lugar
protected:
double interestRate; // Acessível nesta classe e em classes derivadas
private:
double balance; // Acessível apenas dentro desta classe
};Por padrão, todos os membros em uma classe são private se nenhum especificador for fornecido.
Exemplo demonstrando controle de acesso:
class Account {
private:
double balance;
public:
Account() : balance(0) {}
void deposit(double amount) {
balance += amount; // OK - dentro da classe
}
};
int main() {
Account acc;
acc.deposit(100); // OK - deposit é público
// acc.balance = 500; // ERRO - balance é privado
}Melhor prática: Torne os membros de dados privados e forneça métodos públicos para interagir com eles de forma segura.
Experimente você mesmo
#include <iostream>
#include <string>
#include <iomanip>
#include "Employee.h"
using namespace std;
int main() {
// Ler entrada
string name;
string department;
string salaryStr;
getline(cin, name);
getline(cin, department);
getline(cin, salaryStr);
double salary = stod(salaryStr);
// Definir a precisão para a saída do salário
cout << fixed << setprecision(2);
// TODO: Criar um objeto Employee com os valores de entrada
// TODO: Imprimir o nome do funcionário acessando o membro público diretamente
// Formato: "Direct access - Name: <name>"
// TODO: Imprimir o departamento usando o método getter
// Formato: "Via getter - Department: <department>"
// TODO: Imprimir o salário usando o método getter
// Formato: "Via getter - Salary: $<salary>"
// TODO: Dar ao funcionário um aumento de 5000.0
// TODO: Imprimir "After raise:"
// TODO: Chamar displayInfo() para mostrar as informações atualizadas
return 0;
}
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
1Fundamentos de OOP
Arquivos ExternosBuild e Compilação em C++Arquivos Header e SourceNamespaces e EscopoIntrodução a OOP em C++Classes vs ObjetosO Ponteiro 'this'Métodos (Funções Membro)Atributos (Membros de Dados)Básico de Ctors e DtorsRecapitulação - Calculadora Simples4Propriedades de Classe
Membros de Instância vs EstáticosGetters e SettersFunções de Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRecapitulação - Gerenciador de Conta Bancária7Herança
Herança BásicaNíveis de Acesso na HerançaOrdem de Chamada de Ctor e DtorSobrescrita de MétodosFunções Virtuais e VTableHerança MúltiplaHerança VirtualRecapitulação - Hierarquia de Funcionários2Gerenciamento de Memória
Memória Stack vs HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Smart Pointers em C++RAII em C++Recapitulação - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de Acesso em C++Especificadores de Acesso em DetalhesOcultação de InformaçãoStruct vs ClassClasses Aninhadas e InternasRecapitulação - Sistema de Registros de Alunos8Polimorfismo
Polimorfismo de Compilação vs Tempo de ExecuçãoSobrecarga de FunçõesFunções Virtuais RevisitadasFunções Virtuais PurasClasses AbstratasDesign de Interfaces em C++Dynamic Casting e RTTIRecapitulação - Calculadora de Formas3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentaçãoListas de Inicialização do ConstrutorConstrutores DelegadosMergulho Profundo em DestrutoresRegra dos Três / Cinco / ZeroRecapitulação - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de StreamSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçãoTemplates de ClasseEspecialização de TemplatesTemplates VariádicosFundamentos de SFINAE e Type TraitsRecapitulação - Container Genérico