Ocultação de informações
Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy. Lição 36 de 104.
Ocultação de informações vai além de apenas usar especificadores de acesso. É um princípio de design no qual você oculta não apenas os dados, mas também os detalhes de implementação de como sua classe funciona internamente.
O objetivo é expor apenas o que os usuários da sua classe precisam saber, mantendo todo o restante oculto. Isso permite alterar a implementação interna sem afetar o código que usa sua classe:
class Temperature {
double kelvin; // Representação interna - detalhe oculto
public:
void setCelsius(double c) {
kelvin = c + 273.15; // Conversão oculta do usuário
}
double getCelsius() const {
return kelvin - 273.15;
}
double getFahrenheit() const {
return (kelvin - 273.15) * 9.0/5.0 + 32;
}
};Os usuários dessa classe não sabem (nem precisam saber) que a temperatura é armazenada internamente em Kelvin. Se mais tarde você decidir armazená-la em Celsius, basta alterar a implementação privada — a interface pública permanece inalterada.
Essa separação entre interface e implementação oferece vários benefícios: reduz a complexidade para os usuários da sua classe, evita o uso acidental indevido de dados internos e torna seu código mais fácil de manter. Quando os detalhes internos ficam ocultos, você pode otimizar ou refatorar livremente sem quebrar o código existente que depende da sua classe.
Desafio
FácilVamos criar uma classe Distance que demonstra o ocultamento de informações armazenando internamente as distâncias em centímetros, enquanto fornece uma interface simples para trabalhar com diferentes unidades. Quem usar sua classe não precisará saber (nem se importar) como a distância é armazenada internamente: basta trabalhar com a unidade que for mais conveniente.
Você criará dois arquivos para organizar seu código:
Distance.h: defina uma classeDistanceque oculte sua representação interna, expondo ao mesmo tempo uma interface pública flexível. Internamente, armazene a distância em centímetros (como umdouble). Este é o detalhe de implementação oculto. Sua interface pública deve permitir aos usuários:- Definir a distância usando
setMeters(double m),setCentimeters(double cm)ousetKilometers(double km) - Obter a distância usando
getMeters(),getCentimeters()ougetKilometers(): todos devem ser métodos const - Somar duas distâncias usando
add(const Distance& other), que retorna um novo objetoDistance
Inclua um construtor padrão que inicialize a distância como zero. A lógica de conversão deve ficar oculta dentro dos seus métodos: os usuários simplesmente chamam
setKilometers(5)egetMeters()sem se preocupar com o formato de armazenamento interno.- Definir a distância usando
main.cpp: demonstre que os usuários podem trabalhar com sua classe sem conhecer a representação interna. Leia dois valores de distância da entrada: o primeiro em metros e o segundo em quilômetros. Em seguida:- Crie um objeto
Distancee defina seu valor usando o valor em metros - Imprima
"In meters: <value> m" - Imprima
"In centimeters: <value> cm" - Imprima
"In kilometers: <value> km" - Crie um segundo objeto
Distancee defina seu valor usando o valor em quilômetros - Some as duas distâncias e armazene o resultado
- Imprima
"Combined in meters: <value> m"
- Crie um objeto
A vantagem do ocultamento de informações é que, posteriormente, você poderia alterar o armazenamento interno de centímetros para milímetros (ou qualquer outra unidade) sem mudar a forma como os usuários interagem com sua classe. A interface pública permanece estável mesmo que a implementação mude.
Formate todos os valores de saída com duas casas decimais usando std::fixed e std::setprecision(2) de <iomanip>. Converta as strings de entrada para valores double usando std::stod().
Referência de conversão: 1 metro = 100 centímetros, 1 quilômetro = 1000 metros.
Experimente você mesmo
#include <iostream>
#include <string>
#include <iomanip>
#include "Distance.h"
using namespace std;
int main() {
// Ler valores de entrada
string metersInput, kmInput;
cin >> metersInput; // Primeiro valor em metros
cin >> kmInput; // Second value in kilometers
// Converter strings para doubles usando std::stod()
double metersValue = stod(metersInput);
double kmValue = stod(kmInput);
// Definir formatação de saída
cout << fixed << setprecision(2);
// TODO: Criar o primeiro objeto Distance e defini-lo usando o valor em metros
// TODO: Imprimir "In meters: <value> m"
// TODO: Print "In centimeters: <value> cm"
// TODO: Print "In kilometers: <value> km"
// TODO: Criar o segundo objeto Distance e defini-lo usando o valor em quilômetros
// TODO: Somar as duas distâncias usando o método add()
// TODO: Print "Combined in meters: <value> m"
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