C++
Classes & Objects
Introduction to C++ showed one class as a preview. This
chapter is the concept in full: what a class actually is, what an object is (they're not the same
thing), how access control really works, and where a class fits next to the plain
struct you already know.
- What it is
- A class is a type definition — the blueprint. An object is one instance of that type — an actual thing built from the blueprint, occupying real memory.
- Mental model
- A class is an architect's blueprint for a house; an object is one actual house built from it. You can build many houses (objects) from one blueprint (class), each with its own separate rooms (member data).
- Key numbers
- Three access levels:
public,private,protected(the third covered in Inheritance & Polymorphism); aclass's members default toprivate, astruct's default topublic— the only real difference between the two keywords in C++. - Reach for it when
- Data and the operations on it are always used together, and you want the compiler to actually enforce which code is allowed to touch the data directly.
Class vs. object
class SensorReading {
public:
int timestamp;
float value;
};
SensorReading r1; // r1 is an OBJECT — one instance of the SensorReading class
SensorReading r2; // r2 is a SEPARATE object — its own independent copy of the fields
r1.timestamp = 1000;
r2.timestamp = 2000; // r1.timestamp is still 1000 — completely independent
SensorReading the class exists once, as a definition the compiler reads. r1
and r2 the objects exist as many times as you create them, each with its own separate
storage for every member field — exactly like two variables of the same
struct type in C.
Access control: public, private
class BankAccount {
public:
void deposit(float amount) {
if (amount > 0) balance += amount; // validated, controlled access
}
float getBalance() { return balance; }
private:
float balance = 0; // cannot be touched directly from outside this class
};
int main() {
BankAccount acc;
acc.deposit(100);
// acc.balance = -500; // COMPILE ERROR — balance is private
return 0;
}
This is the actual point of encapsulation: balance can only ever change through
deposit, which validates the amount first. In equivalent C, nothing stops any function
anywhere in the program from writing directly into a struct's field, skipping any validation entirely —
C++'s access control makes that a compile error instead of a discipline problem.
Member functions
A function declared inside a class (like deposit and getBalance above) is a
member function (or method) — it's called on a specific object using
the dot operator, and it can access that object's own private data without any special syntax:
acc.deposit(100); // calls deposit ON the acc object specifically
acc.getBalance(); // returns acc's OWN balance, not some other account's
Underneath, the compiler passes the object itself as a hidden first argument to every member function call — conceptually the same "pass the struct as the first argument" pattern from C's Functions, just handled automatically instead of written by hand every time.
class vs. struct in C++
Unlike in C, a C++ struct can also have member functions and access control — the two
keywords are functionally almost identical in C++. The only difference is the default
access level:
| Keyword | Default member access |
|---|---|
class | private |
struct | public |
Common convention: use struct for simple, data-only bundles with no invariants to protect
(matching how C's structs are normally used), and
class when there's real encapsulated behavior and data that needs protecting.
What an object actually looks like in memory
Real-world applications
- Hardware driver wrappers — a
UARTclass exposingsend()/receive()methods while keeping the underlying register access entirely private and validated. - Game entities — a
PlayerorEnemyclass bundling position, health, and behavior into one self-contained, independently-instantiable unit. - GUI widgets — a
Buttonclass encapsulating its own state (pressed, position, label) and the logic for handling a click, independent of every other button on screen.
Gotchas
- Forgetting that
classdefaults toprivateis a common beginner error — a class with no explicitpublic:label has every member inaccessible from outside, including the constructor, which then can't be called at all. - Overusing
publicdata members defeats the entire point of encapsulation — if every field is public, a C++ class provides no real protection benefit over a plain C struct, just extra syntax. - A member function can only access the calling object's own data —
acc1.deposit(100)can never accidentally touchacc2's balance, even though both are the same class; this isolation is automatic, not something you have to write by hand.