Information Hiding
Part of the Object Oriented Programming section of Coddy's C++ journey — lesson 36 of 104.
Information hiding goes beyond just using access specifiers. It's a design principle where you hide not only data, but also the implementation details of how your class works internally.
The goal is to expose only what users of your class need to know, while keeping everything else hidden. This allows you to change the internal implementation without affecting code that uses your class:
class Temperature {
double kelvin; // Internal representation - hidden detail
public:
void setCelsius(double c) {
kelvin = c + 273.15; // Conversion hidden from user
}
double getCelsius() const {
return kelvin - 273.15;
}
double getFahrenheit() const {
return (kelvin - 273.15) * 9.0/5.0 + 32;
}
};Users of this class don't know (or need to know) that temperature is stored in Kelvin internally. If you later decide to store it in Celsius instead, you only change the private implementation - the public interface remains unchanged.
This separation between interface and implementation provides several benefits: it reduces complexity for users of your class, prevents accidental misuse of internal data, and makes your code easier to maintain. When the internal details are hidden, you're free to optimize or refactor without breaking existing code that depends on your class.
Challenge
EasyLet's build a Distance class that demonstrates information hiding by storing distances internally in meters while providing a clean interface for working with different units. Users of your class won't need to know (or care) how the distance is stored internally — they'll just work with whatever unit is convenient for them.
You'll create two files to organize your code:
Distance.h: Define aDistanceclass that hides its internal representation while exposing a flexible public interface. Internally, store the distance in centimeters (as adouble) — this is your hidden implementation detail. Your public interface should allow users to:- Set the distance using
setMeters(double m),setCentimeters(double cm), orsetKilometers(double km) - Get the distance using
getMeters(),getCentimeters(), orgetKilometers()— all should be const methods - Add two distances together with
add(const Distance& other)which returns a newDistanceobject
Include a default constructor that initializes the distance to zero. The conversion logic should be hidden inside your methods — users just call
setKilometers(5)andgetMeters()without worrying about the internal storage format.- Set the distance using
main.cpp: Demonstrate that users can work with your class without knowing the internal representation. Read two distance values from input: the first in meters, the second in kilometers. Then:- Create a
Distanceobject and set it using the meters value - Print
"In meters: <value> m" - Print
"In centimeters: <value> cm" - Print
"In kilometers: <value> km" - Create a second
Distanceobject and set it using the kilometers value - Add the two distances together and store the result
- Print
"Combined in meters: <value> m"
- Create a
The beauty of information hiding is that you could later change the internal storage from centimeters to millimeters (or anything else) without changing how users interact with your class. The public interface remains stable even if the implementation changes.
Format all output values with two decimal places using std::fixed and std::setprecision(2) from <iomanip>. Convert input strings to doubles using std::stod().
Conversion reference: 1 meter = 100 centimeters, 1 kilometer = 1000 meters.
Cheat sheet
Information hiding is a design principle where you hide implementation details of how your class works internally, exposing only what users need to know.
This allows you to change the internal implementation without affecting code that uses your class:
class Temperature {
double kelvin; // Internal representation - hidden detail
public:
void setCelsius(double c) {
kelvin = c + 273.15; // Conversion hidden from user
}
double getCelsius() const {
return kelvin - 273.15;
}
double getFahrenheit() const {
return (kelvin - 273.15) * 9.0/5.0 + 32;
}
};Users don't know (or need to know) that temperature is stored in Kelvin internally. If you later change the storage format, only the private implementation changes - the public interface remains unchanged.
Benefits of information hiding:
- Reduces complexity for users of your class
- Prevents accidental misuse of internal data
- Makes code easier to maintain and refactor
- Allows optimization without breaking existing code
Try it yourself
#include <iostream>
#include <string>
#include <iomanip>
#include "Distance.h"
using namespace std;
int main() {
// Read input values
string metersInput, kmInput;
cin >> metersInput; // First value in meters
cin >> kmInput; // Second value in kilometers
// Convert strings to doubles using std::stod()
double metersValue = stod(metersInput);
double kmValue = stod(kmInput);
// Set output formatting
cout << fixed << setprecision(2);
// TODO: Create first Distance object and set it using meters value
// TODO: Print "In meters: <value> m"
// TODO: Print "In centimeters: <value> cm"
// TODO: Print "In kilometers: <value> km"
// TODO: Create second Distance object and set it using kilometers value
// TODO: Add the two distances together using the add() method
// TODO: Print "Combined in meters: <value> m"
return 0;
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesC++ Build & CompilationHeader Files & Source FilesNamespaces & ScopeIntroduction to OOP in C++Classes vs ObjectsThe 'this' PointerMethods (Member Functions)Attributes (Data Members)Ctors & Dtors BasicsRecap - Simple Calculator4Class Properties
Instance vs Static MembersGetters and SettersConst Member FunctionsMutable KeywordStatic Methods and VariablesFriend Functions & ClassesRecap - Bank Account Manager7Inheritance
Basic InheritanceInheritance Access LevelsCtor & Dtor Call OrderMethod OverridingVirtual Functions & VTableMultiple InheritanceVirtual InheritanceRecap - Employee Hierarchy2Memory Management
Stack vs Heap MemoryPointers and ReferencesDynamic Memory (new/delete)Smart Pointers in C++RAII in C++Recap - Dynamic Array Manager5Encapsulation
Access Specifiers in C++Access Specifiers In DepthInformation HidingStruct vs ClassNested & Inner ClassesRecap - Student Records System8Polymorphism
Compile vs Runtime PolymorphFunction OverloadingVirtual Functions RevisitedPure Virtual FunctionsAbstract ClassesInterface Design in C++Dynamic Casting & RTTIRecap - Shape Calculator3Constructors & Destructors
Default ConstructorParameterized ConstructorCopy ConstructorMove ConstructorConstructor Init ListsDelegating ConstructorsDestructor Deep DiveRule of Three / Five / ZeroRecap - String Class6Operator Overloading
Intro to Operator OverloadArithmetic Operator OverloadComparison Operator OverloadStream OperatorsAssignment Operator Overload[] and () Operator OverloadType Conversion OperatorsRecap - Matrix Class9Templates
Function TemplatesClass TemplatesTemplate SpecializationVariadic TemplatesSFINAE & Type Traits BasicsRecap - Generic Container