C++ Classes and Objects

Build classes with private data, public member functions, constructors, const methods and destructors.

Lesson 13 of 44Intermediate18 min read

In the structs lesson you grouped data together. A class goes further: it bundles data with the functions that work on it, and it controls who can change that data. That control is called encapsulation, and it's the heart of object-oriented programming.

Think of a bank account. Its balance should never go negative, and deposits must always be positive. If the balance is a public member, any line of code anywhere can break those rules. In a class, the balance is private, and the only way to change it is through public member functions such as deposit() and withdraw(), which check the rules every time.

In this lesson you'll write classes with private data and public functions, set objects up correctly with constructors, mark read-only functions as const, learn what a destructor does, and see how real projects split a class into a header and a source file.

A first class

C++
class Counter {
private:
    int count = 0;

public:
    void click() { count++; }
    int value() const { return count; }
};

Counter c;
c.click();
c.click();
cout << c.value();   // 2
  • private: members can only be used inside the class's own functions.
  • public: members can be used by any code.
  • Functions declared inside a class are member functions (often called methods). They can use the object's members directly.
  • Each object, or instance, has its own copy of the data members: two counters count separately.
  • Like structs, a class definition ends with a semicolon.

Constructors and initializer lists

A constructor is a member function with the same name as the class and no return type. It runs automatically when an object is created, so the object starts in a valid state:

C++
class Account {
    string owner;
    double balance;
public:
    Account(const string& o, double b) : owner(o), balance(b) {}
};

Account acc("Sam", 50.0);

The part after the colon is the member initializer list, the preferred way to set members, because it initialises them directly instead of assigning after they've been created. You can have several constructors with different parameters, and a constructor with no parameters is called the default constructor.

const member functions, getters and setters

Mark a member function const when it doesn't change the object: double getBalance() const. The compiler then stops it from modifying members by accident, and lets it be called on const objects and through const& parameters.

Functions that read a private member are often called getters, and functions that change one with checks are setters. Only add them when they're needed: a class with a getter and setter for every member is barely more protected than a struct. Better classes offer meaningful actions, like deposit(amount), rather than setBalance(x).

Destructors and header files

A destructor, written ~ClassName(), runs automatically when an object is destroyed, for example when it goes out of scope at the end of a block. It's used to release resources such as files or network connections. Thanks to std::string, std::vector and smart pointers, most classes don't need to write one.

In larger projects, each class is split into two files: a header (Account.h) containing the class definition with function declarations, and a source file (Account.cpp) containing the function bodies, written as double Account::getBalance() const { ... }. Other files #include "Account.h" to use the class.

C++ Classes Syntax

Class syntax

class Name {
private:
    Type member;
public:
    Name(Type m) : member(m) {}       // constructor
    Type get() const { return member; }
    void doSomething(Type x);
    ~Name() {}                         // destructor (rarely needed)
};

void Name::doSomething(Type x) { ... }  // defined outside the class
Name obj(value);
obj.get();

C++ Classes Summary

  • A class bundles private data with public member functions: encapsulation.
  • Constructors have the class's name and no return type; use initializer lists to set members.
  • Mark functions that don't change the object as const.
  • A destructor ~Name() runs when an object is destroyed.
  • Real projects put the class in a .h header and the function bodies in a .cpp file.

C++ Classes Examples

Each example shows the code, the output it produces and what each part does.

Example 1

A bank account class

C++
#include <iostream>
#include <string>
using namespace std;

class Account {
private:
    string owner;
    double balance;

public:
    Account(const string& o, double start) : owner(o), balance(start) {}

    bool deposit(double amount) {
        if (amount <= 0) return false;
        balance += amount;
        return true;
    }

    bool withdraw(double amount) {
        if (amount <= 0 || amount > balance) return false;
        balance -= amount;
        return true;
    }

    double getBalance() const { return balance; }
    string getOwner() const { return owner; }
};

int main() {
    Account acc("Sam", 50);
    acc.deposit(25);
    cout << boolalpha;
    cout << "Withdraw 100: " << acc.withdraw(100) << endl;
    cout << "Deposit -5: " << acc.deposit(-5) << endl;
    cout << acc.getOwner() << " has " << acc.getBalance() << endl;
    return 0;
}
Output
Withdraw 100: false
Deposit -5: false
Sam has 75
Line-by-line explanation
  1. Lines 6 to 8The data is private, so only the class's own functions can change it.
  2. Line 11The constructor uses an initializer list to set both members.
  3. Lines 13 to 23Every change goes through a function that checks the rules.
  4. Lines 25 to 26const getters let other code read the values safely.
  5. Line 31Trying acc.balance = -100; here would not compile, because balance is private.
Example 2

Several objects and a defined-outside function

C++
#include <iostream>
#include <string>
using namespace std;

class Rectangle {
    double width, height;
public:
    Rectangle(double w, double h) : width(w), height(h) {}
    double area() const;
    bool isSquare() const { return width == height; }
};

double Rectangle::area() const {
    return width * height;
}

int main() {
    Rectangle a(3, 4), b(5, 5);
    cout << "a: " << a.area() << ", square? " << a.isSquare() << endl;
    cout << "b: " << b.area() << ", square? " << b.isSquare() << endl;
    return 0;
}
Output
a: 12, square? 0
b: 25, square? 1
Line-by-line explanation
  1. Line 5Class members are private by default, so width and height are private.
  2. Line 9area() is declared inside the class...
  3. Lines 13 to 15...and defined outside it, using Rectangle:: to say which class it belongs to.
  4. Line 18Two objects, each with its own width and height.
Example 3

When constructors and destructors run

C++
#include <iostream>
#include <string>
using namespace std;

class Logger {
    string name;
public:
    Logger(const string& n) : name(n) { cout << "Start " << name << endl; }
    ~Logger() { cout << "End " << name << endl; }
};

int main() {
    Logger outer("main");
    {
        Logger inner("block");
        cout << "Working..." << endl;
    }
    cout << "Back in main" << endl;
    return 0;
}
Output
Start main
Start block
Working...
End block
Back in main
End main
Line-by-line explanation
  1. Lines 8 to 9The constructor and destructor print a message so you can see when they run.
  2. Lines 14 to 17inner is destroyed at the closing brace of its block.
  3. Line 19outer is destroyed when main ends, after everything else.

Common C++ Classes Mistakes

Forgetting the semicolon after a class

Don't
class Point {
    int x, y;
}
Do
class Point {
    int x, y;
};

Accessing private members from outside

Don't
Account acc("Sam", 50);
acc.balance = 1000000;      // error: 'balance' is private
Do
Account acc("Sam", 50);
acc.deposit(100);

A getter that isn't const

Don't
double getBalance() { return balance; }
void show(const Account& a) { cout << a.getBalance(); }   // error
Do
double getBalance() const { return balance; }

Functions called on const objects or const references must themselves be const.

C++ Classes in Real Projects

Classes in C++ software

Game engines model players, enemies and cameras as classes, GUI toolkits like Qt use classes for windows and buttons, and the standard library itself is built from classes: std::string, std::vector and std::fstream all keep their data private and offer safe member functions. The constructor and destructor pattern you saw with Logger is how they manage memory and files automatically.

C++ Classes FAQ

What is the this pointer in C++?

Inside a member function, this is a pointer to the object the function was called on. You rarely need to write it, because members can be used directly, but it's useful when a parameter has the same name as a member: this->name = name;. Functions that return the object itself, so calls can be chained, end with return *this;.

What is a static member variable?

A static data member belongs to the class rather than to any one object, so all objects share a single copy. It's handy for things like counting how many objects have been created. Since C++17 you can declare and initialise it in the class with inline static int count = 0;, and read it from outside as Player::count.

What does explicit mean on a constructor?

A constructor that takes one argument also lets C++ convert that type into your class silently, so a function expecting a Meters would accept a plain 3.0. Marking the constructor explicit turns that off: callers must write Meters(3.0) to show they mean it. Most single-argument constructors should be explicit.

What happens when I copy an object in C++?

Writing Account b = a; or passing an object by value calls the copy constructor, which the compiler writes for you and which copies every member in turn. That's exactly right for members such as string, vector and numbers, so most classes need nothing extra. After the copy, the two objects are independent: changing one doesn't affect the other.

Can one constructor call another constructor?

Yes, since C++11, with a delegating constructor. Name the other constructor in the member initializer list: Rect(int side) : Rect(side, side) {} builds a square by reusing the two-argument constructor. This keeps the setup and validation code in one place instead of repeating it.

C++ Classes Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Complete the class so name can only be used inside the class.

class Pet {
:
    string name;
:
    Pet(const string& n) : name(n) {}
};
Predict the outputeasy

What does this print?

class Counter {
    int n = 0;
public:
    void add() { n += 2; }
    int get() const { return n; }
};
Counter a, b;
a.add(); a.add(); b.add();
cout << a.get() << " " << b.get();
Multiple choicemedium

What is a member initializer list?

Multiple choicemedium

What does const after a member function's brackets mean?

Predict the outputhard

In what order are messages printed when an object made in a block reaches the block's closing brace?

C++ Classes Quiz

5 questions to check what you learned.

  1. What is the default access for class members in C++?

    • private
    • public
    • protected
    • There is no default
  2. What is encapsulation?

    • Putting classes in separate files
    • Creating many objects
    • Inheriting from a class
    • Keeping data private and allowing changes only through member functions
  3. How is a destructor written?

    • destroy Name()
    • Name::delete()
    • ~Name()
    • void Name()
  4. What does double Account::getBalance() const mean outside a class?

    • A new class
    • The definition of Account's getBalance member function
    • A global function called Account
    • A call to getBalance
  5. Why prefer deposit(amount) over setBalance(x)?

    • It describes a real action and can enforce the class's rules
    • It's shorter
    • Setters aren't allowed in C++
    • It's faster