Inheritance in C++

    Atul Kabra4 min readUpdated

    Inheritance lets one class (the derived class) reuse and extend another class (the base class). The derived class automatically gets the base class's data and functions, then adds or changes whatever it needs. It models an "is-a" relationship: a Manager is an Employee, a Circle is a Shape.

    Here is the simplest version.

    Base and derived classes

    #include <iostream>
    #include <string>
    
    // base class
    class Employee {
    public:
        std::string name;
    
        void clockIn() const {
            std::cout << name << " clocked in\n";
        }
    };
    
    // derived class: Manager IS-AN Employee
    class Manager : public Employee {
    public:
        int teamSize = 0;
    
        void report() const {
            std::cout << name << " manages " << teamSize << " people\n";
        }
    };
    
    int main() {
        Manager m;
        m.name = "Priya";   // inherited from Employee
        m.teamSize = 4;     // added by Manager
        m.clockIn();        // inherited function
        m.report();         // own function
    }
    

    Output:

    Priya clocked in
    Priya manages 4 people
    

    Manager never re-declares name or clockIn — it inherits them from Employee.

    The three access levels

    You almost always use public inheritance (class Manager : public Employee), which keeps the base's public members public. Inside the base class you can also mark members protected: those are hidden from outside code but visible to derived classes.

    class Account {
    protected:
        double balance = 0.0;   // derived classes can use this; outsiders cannot
    public:
        double getBalance() const { return balance; }
    };
    
    class SavingsAccount : public Account {
    public:
        void addInterest(double rate) {
            balance += balance * rate;  // OK: balance is protected
        }
    };
    

    Use protected sparingly — it widens the interface that subclasses depend on.

    Want to learn this properly?

    Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.

    Browse courses

    Calling the base constructor

    When a derived object is created, the base part is constructed first. Pass arguments up with the initializer list.

    #include <iostream>
    #include <string>
    
    class Shape {
    public:
        std::string color;
        Shape(std::string c) : color(std::move(c)) {}
    };
    
    class Circle : public Shape {
    public:
        double radius;
        // forward the color to the base, then set radius
        Circle(std::string c, double r)
            : Shape(std::move(c)), radius(r) {}
    };
    
    int main() {
        Circle circ{"red", 2.5};
        std::cout << circ.color << " circle, r=" << circ.radius << "\n";
    }
    

    Overriding inherited behaviour

    A derived class can replace a base function by redefining it. (To switch behaviour through a base pointer at run time, you need virtual functions — covered separately.)

    class Animal {
    public:
        void speak() const { std::cout << "...\n"; }
    };
    
    class Dog : public Animal {
    public:
        void speak() const { std::cout << "Woof!\n"; } // hides Animal::speak
    };
    

    Prefer composition when it is not really "is-a"

    Inheritance is for genuine "is-a" relationships. If a Car merely has an Engine, store an Engine member instead of inheriting from it. Overusing inheritance produces fragile, tangled hierarchies.

    // composition: a Car HAS-AN Engine (not "is-an")
    class Engine {
    public:
        void start() { /* ... */ }
    };
    
    class Car {
        Engine engine;          // a member, not a base class
    public:
        void ignite() {
            engine.start();     // delegate to the held object
        }
    };
    

    A good rule of thumb: if you would never substitute the derived object wherever the base is expected, it is probably a "has-a" relationship and composition is the cleaner choice.

    Common mistakes

    • Forgetting public in the inheritance. class Manager : Employee defaults to private inheritance, which hides the base's public members. Write : public Employee.
    • Trying to use protected data from outside the hierarchy. Only the class itself and its derived classes can touch protected members.
    • Not forwarding constructor arguments. If the base has no default constructor, the derived class must call it explicitly in the initializer list.
    • Reaching for inheritance when composition fits. Ask "is-a or has-a?" before deriving.

    FAQ

    What is the difference between public, protected, and private members? public is visible everywhere, protected is visible to the class and its derived classes, and private is visible only inside the class itself.

    Can a class inherit from more than one base? Yes — C++ supports multiple inheritance. It is powerful but can cause ambiguity, so most beginners should start with single inheritance.

    Keep learning

    Learn it properly with guided projects — join the waitlist for our C++ Programming course in Jalgaon.

    Want to learn this properly?

    Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.

    Browse courses
    Atul Kabra

    Founder, Infoplanet

    Atul Kabra founded Infoplanet in 2001 and has spent over two decades teaching programming — C, C++, Java, databases and more — to students across Maharashtra.

    Related guides