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.
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 entre os dois — funcionam como privados para o mundo externo, mas as 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; // ERROR - balance é privado
}Por padrão, todos os membros de uma classe são privados quando nenhum especificador é fornecido. Isso incentiva você a decidir explicitamente o que deve ser exposto. A prática geral é tornar os membros de dados privados e fornecer métodos públicos para interagir com eles com segurança.
Desafio
FácilVamos criar 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 na qual alguns dados são completamente privados, alguns são acessíveis a possíveis subclasses e alguns estão abertos a todos.
Você criará dois arquivos para organizar seu código:
Employee.h: Defina uma classeEmployeeque use os três especificadores de acesso para proteger os dados adequadamente:- Public: o
namedo funcionário (string). Isso pode ser acessado de qualquer lugar - Protected: o
departmentdo funcionário (string): acessível dentro da classe e por classes derivadas, mas não externamente - Private: o
salarydo funcionário (double): acessível somente dentro da própria classe - Um construtor que receba name, department e salary para inicializar os três membros
- Um método público
getSalary()que retorne o valor privado de salary - Um método público
getDepartment()que retorne o valor protegido de department - Um método público
giveRaise(double amount)que aumente o salary pelo amount informado (somente se amount for positivo) - Um método público
displayInfo()que imprima as informações do funcionário no formato:"Name: <name>, Department: <department>, Salary: $<salary>"
- Public: o
main.cpp: Demonstre como os especificadores de acesso funcionam interagindo com um objeto Employee. Leia o name, o department e o salary de um funcionário a partir da entrada (três linhas separadas) e, então:- Crie um
Employeecom os valores informados - Imprima o name do funcionário acessando diretamente o membro público:
"Direct access - Name: <name>" - Imprima o department usando o getter:
"Via getter - Department: <department>" - Imprima o salary usando o getter:
"Via getter - Salary: $<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 salary com duas casas decimais usando std::fixed e std::setprecision(2) de <iomanip>. Converta a entrada de salary de string para double usando std::stod().
A principal ideia aqui é que, embora você possa acessar name diretamente de main, não pode acessar department ou salary diretamente. Você deve usar os métodos públicos getter. Isso é encapsulamento em ação: a classe controla como seus dados são acessados e modificados.
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 precisão para a saída do salário
cout << fixed << setprecision(2);
// TODO: Crie um objeto Employee com os valores de entrada
// TODO: Imprima o nome do funcionário acessando o membro público diretamente
// Format: "Direct access - Name: <name>"
// TODO: Imprima o departamento usando o método getter
// Format: "Via getter - Department: <department>"
// TODO: Imprima o salário usando o método getter
// Format: "Via getter - Salary: $<salary>"
// TODO: Dê ao funcionário um aumento de 5000.0
// TODO: Imprima "After raise:"
// TODO: Chame 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 POO
Arquivos externosBuild e compilação em C++Arquivos de cabeçalho e arquivos-fonteNamespaces e escopoIntrodução à POO em C++Classes vs. objetosO ponteiro 'this'Métodos (funções membro)Atributos (membros de dados)Noções básicas de construtores e destruidoresRevisão - calculadora simples4Propriedades de Classe
Membros de Instância vs. EstáticosGetters e SettersFunções Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRevisão - Gerenciador de Contas Bancárias7Herança
Herança básicaNíveis de acesso da herançaOrdem de chamada de construtor e destrutorSobrescrita de métodosFunções virtuais e VTableHerança múltiplaHerança virtualRevisão - Hierarquia de funcionários10Visão geral da STL
Visão geral e filosofia da STLContêineres da STLIteradoresAlgoritmos da STLFunctors e expressões lambdaRecapitulação - Frequência de palavras13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonFactory e Abstract FactoryPadrão BuilderPadrão ObserverPadrão Strategy2Gerenciamento de Memória
Memória Stack vs. HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Ponteiros Inteligentes em C++RAII em C++Revisão - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de acesso em C++Especificadores de acesso em profundidadeOcultação de informaçõesStruct vs ClasseClasses aninhadas e internasRecapitulação - Sistema de registros de alunos8Polimorfismo
Polimorfismo em compilação vs. execuçãoSobrecarga de funçõesFunções virtuais revisadasFunções virtuais purasClasses abstratasDesign de interfaces em C++Conversão dinâmica e RTTIRecapitulação — Calculadora de formas11Conceitos Avançados de OOP
Composição vs. HerançaMixins via CRTPIdioma PimplApagamento de TiposClasses Enum e Tipagem ForteTratamento de Exceções em OOPHierarquias de Exceções Personalizadas14Padrões de Projeto — Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositeRAII como Padrão3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentoListas de Inicialização do ConstrutorConstrutores DelegantesAprofundamento em DestrutoresRegra dos Três / Cinco / ZeroRevisão - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de FluxoSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçõesTemplates de ClassesEspecialização de TemplatesTemplates VariádicosNoções Básicas de SFINAE e Traits de TiposRecapitulação - Contêiner GenéricoPratique por conta própria: Compilador de C++ online