Skip to main content
    Courses/C++/Object-Oriented Programming

    Lesson 9 • Intermediate

    Object-Oriented Programming

    By the end of this lesson you'll be able to design your own C++ classes — bundling data with the functions that act on it, protecting that data behind a clean interface, and bringing objects to life with constructors. This is the paradigm that organises every large C++ program you'll ever read.

    What You'll Learn

    • Define a class and create objects from it
    • Add data members and member functions (methods)
    • Control access with public, private, and protected
    • Write default, parameterized, and initializer-list constructors
    • Use destructors and the this pointer correctly
    • Apply encapsulation with getters/setters, and know struct vs class

    💡 Real-World Analogy

    A class is a cookie cutter; an object is a cookie you stamp out with it. The cutter defines the shape (what data and behaviour every cookie has), but each cookie is its own thing with its own decorations (its own data). You can make a hundred cookies from one cutter, and changing the icing on one doesn't touch the others. The private part of a class is like the secret recipe sealed inside — people can eat the cookie (use its methods) without ever seeing, or messing up, the recipe.

    1. Classes, Objects & Members

    A class bundles together data members (the variables each object stores) and member functions, also called methods (the functions that act on that data). An object is one concrete instance of the class. You reach into an object with the . (dot) operator: myDog.bark(). Read this worked example, run it, and notice that each object keeps its own copy of the data.

    Worked example: a Dog class

    Read every comment, run it, and check the output matches.

    Try it Yourself »
    C++
    #include <iostream>
    #include <string>
    using namespace std;
    
    // A class is a BLUEPRINT. It bundles DATA (members) with the
    // FUNCTIONS that work on that data (member functions / methods).
    class Dog {
    public:                      // anyone can touch what's below this label
        // --- data members (the state each object carries) ---
        string name;
        int ageYears;
    
        // --- member function (a method = a function that lives on the class) ---
        void bark() {
            cout << name << " says: Wo
    ...

    Your turn. The Book class below is almost complete — fill in the two blanks marked ___ using the hints, then run it.

    🎯 Your turn: finish the Book class

    Fill in the ___ blanks, then check your output against the expected line.

    Try it Yourself »
    C++
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Book {
    public:
        // 🎯 YOUR TURN — fill in the blanks marked with ___
    
        // 1) Two data members: a string "title" and an int "pages"
        string title;
        int ___;                 // 👉 name this member  pages
    
        // 2) A member function that prints the book's details
        void show() {
            cout << title << " (" << ___ << " pages)" << endl;  // 👉 print the pages member
        }
    };
    
    int main() {
        Book b;
        b.title = "C++
    ...

    2. Access Specifiers & Encapsulation

    Encapsulation means hiding an object's data and only letting the outside world touch it through safe, controlled methods. You enforce it with access specifiers: private: (only the class itself can see it), public: (anyone with an object can use it), and protected: (the class and any classes that inherit from it — you'll meet inheritance next lesson). The pattern is: keep data private, expose public methods. A method that only reads data is a getter; one that changes it (with validation) is a setter.

    Worked example: a BankAccount that protects its balance

    See how private data plus public methods keep the object valid.

    Try it Yourself »
    C++
    #include <iostream>
    #include <string>
    using namespace std;
    
    class BankAccount {
    private:                     // hidden from the outside world
        string owner;
        double balance;          // NOBODY can set this directly -> it stays valid
    
    public:                      // the safe, controlled "front door"
        // Constructor: runs automatically when an object is created.
        // The : owner(name), balance(...) part is the INITIALIZER LIST.
        BankAccount(string name, double opening)
            : owne
    ...

    Now you try. Complete the constructor's initializer list and add the missing const to the getter:

    🎯 Your turn: finish the Thermostat class

    Complete the initializer list and mark the getter const, then run it.

    Try it Yourself »
    C++
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Thermostat {
    private:
        double tempC;            // private -> protected from bad values
    
    public:
        // 🎯 YOUR TURN — complete the constructor and the getter.
    
        // 1) Constructor: store the starting temperature in tempC
        //    using an initializer list ( : member(value) )
        Thermostat(double start) : ___ {}   // 👉 write  tempC(start)
    
        // 2) A read-only getter that returns tempC
        double getTemp() ___ { return te
    ...

    3. Constructors, this & Destructors

    A constructor is a special method that runs automatically when an object is created — its job is to put the object in a valid starting state. A class can have several: a default constructor (no arguments) and one or more parameterized constructors. The cleanest way to set members is the initializer list — the : member(value) part written before the { body. Inside a method, this is a pointer to the current object, handy when a parameter shares a member's name (this->name = name;). The destructor (named ~ClassName) runs automatically when the object is destroyed — the place to release any resources it held.

    Worked example: default vs parameterized constructors

    Watch the constructors and destructors fire automatically.

    Try it Yourself »
    C++
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Player {
    private:
        string name;
        int score;
    
    public:
        // Default constructor — no arguments. Used when you write  Player p;
        Player() : name("Guest"), score(0) {
            cout << "Default Player created: " << name << endl;
        }
    
        // Parameterized constructor — takes arguments.
        // 'this' is a pointer to THIS object; this->name means "my own name".
        Player(string name, int score) {
            this->name = name;   
    ...

    🔎 Deep Dive: struct vs class

    In C++ a struct and a class are almost identical — both can have data, methods, and constructors. The only real difference is the default access level:

    • struct members are public by default.
    • class members are private by default.

    By convention, reach for struct when you just need a plain bundle of data with no hidden rules (like a 2D Point), and class when you want encapsulation. Picking the right one signals your intent to the next reader.

    struct Point { double x, y; };   // x and y are public
    class  Wallet { double cash; };  // cash is private (hidden)

    Putting It Together: an Inventory

    This program uses everything from the lesson at once — a plain struct Point, an encapsulated Inventory class with a constructor, a private vector, and public methods that control how it changes. Read it line by line; you understand every part now.

    Worked example: struct + class together

    Add or remove items and watch the controlled output update.

    Try it Yourself »
    C++
    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    // A struct: like a class but members are PUBLIC by default.
    // Great for plain bundles of data with no hidden rules.
    struct Point {
        double x;
        double y;
    };
    
    // A class: members are PRIVATE by default -> use it when you want
    // to protect data behind methods (encapsulation).
    class Inventory {
    private:
        string shopName;
        vector<string> items;
    
    public:
        Inventory(string name) : shopName(name) {}
    
        void
    ...

    Pro Tips

    • 💡 Prefer initializer lists: Car(string b) : brand(b) {} initialises members directly and is more efficient than assigning inside the body — and it's required for const members and references.
    • 💡 Mark read-only methods const: a getter like double getBalance() const promises not to change the object, so it works on const objects too.
    • 💡 Keep data private: expose behaviour, not raw fields. It lets you add validation later without breaking callers.
    • 💡 One class, one job: a Car shouldn't also print receipts. Small, focused classes are easier to reuse and test.

    Common Errors (and the fix)

    • Forgetting to initialize members: a member you never set holds a garbage value (e.g. an int might print -858993460). Always set every member in a constructor — ideally via an initializer list.
    • Public data breaks encapsulation: making balance public lets any code write acc.balance = -999; and corrupt the object. Keep it private and change it only through a validating method.
    • Missing constructor: writing Player p("Aria", 100); when the class has no matching constructor gives "no matching function for call to Player::Player(...)". Add a constructor with those parameters.
    • Object slicing (a preview): assigning a derived object to a base-class valueAnimal a = myDog; — copies only the base part and "slices off" the rest. To keep full behaviour, use a reference or pointer (Animal& a = myDog;). You'll cover this fully in Inheritance.
    • "member is private" error: "'balance' is a private member of 'BankAccount'" means you touched a private field from outside. Go through a public getter/setter instead.

    📋 Quick Reference

    ConceptCodeMeaning
    Define a classclass Dog { ... };Blueprint (note the ;)
    Create an objectDog d;One instance
    Access a memberd.name = "Rex";Dot operator
    ConstructorDog(string n) : name(n) {}Runs on creation
    Destructor~Dog() { ... }Runs on destruction
    Read-only getterint get() constWon't modify object
    The object itselfthis->namePointer to current object

    Frequently Asked Questions

    Q: What is the difference between a class and an object in C++?

    A class is the blueprint — it defines what data members and member functions a thing has. An object is one concrete instance built from that blueprint. One Dog class can produce many Dog objects (Rex, Bella), each with its own independent data.

    Q: What is the difference between struct and class in C++?

    Technically only the default access level: members of a struct are public by default, while members of a class are private by default. By convention, use struct for plain data bundles with no hidden rules, and class when you want encapsulation — protecting data behind methods.

    Q: Why should I make data members private?

    Private data is the core of encapsulation. By hiding the data and only exposing controlled getters and setters, you guarantee an object can never hold an invalid state — a BankAccount balance can't be set to a nonsense value from outside, because the only way in is a deposit() method that validates first.

    Q: What does the colon in BankAccount(string n) : owner(n) mean?

    That is a member initializer list. It initialises each data member directly as the object is built, before the constructor body runs. It is more efficient than assigning inside the body and is required for const members and references.

    Q: What is 'this' in C++?

    this is a pointer to the current object — the specific instance a method was called on. You use this->name when a parameter has the same name as a data member, to say 'set MY name to the parameter'. You can write the member name on its own when there is no clash.

    Q: When does the destructor run?

    Automatically, when an object is destroyed — for a local object that is when it goes out of scope (the end of the function). Destructors run in the reverse order objects were created and are where you release resources like memory or file handles.

    Mini-Challenge: Rectangle Class

    No blanks this time — just a brief and an outline to keep you on track. Build the class yourself, run it, and check your output against the example in the comments. This is exactly the kind of small, self-contained class real programs are built from.

    🎯 Mini-Challenge: build a Rectangle class

    Write the members, constructor, and the area() and perimeter() methods.

    Try it Yourself »
    C++
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Rectangle {
        // 🎯 MINI-CHALLENGE: a Rectangle class
        // 1. Private data members: double width and double height.
        // 2. A constructor that takes width and height (use an initializer list).
        // 3. A method  double area() const  that returns width * height.
        // 4. A method  double perimeter() const  that returns 2 * (width + height).
        //
        // ✅ Expected output (for 4 x 3):
        //    Area: 12
        //    Perimeter:
    ...

    🎉 Lesson Complete

    • ✅ A class is a blueprint; an object is one instance of it
    • ✅ Classes bundle data members with member functions (methods)
    • private / public / protected control who can touch each member
    • Constructors set up an object; initializer lists are the clean way to do it
    • ✅ The destructor ~Class() cleans up; this points to the current object
    • Encapsulation = private data + public getters/setters that validate
    • struct defaults to public, class defaults to private
    • Next lesson: Inheritance & Polymorphism — reuse and extend your classes

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service