Skip to content
    SeaCode
    Learning tracksCode ArenaWorkshops & EventsInstructors
    Log inSign up
    C++C++

    C++ fundamentals

    • Your first C++ program
    • Variables and types
    • Operators and input
    • Conditions: if and switch
    • Loops

    Functions and collections

    • Functions
    • References: by value or by reference?
    • Strings and arrays
    • std::vector
    • map, set and unordered_map

    Memory and pointers

    • Pointers
    • Stack, heap, new and delete
    • Smart pointers and RAII

    Classes and OOP

    • struct and class
    • Constructors and destructors
    • Inheritance and virtual functions
    • Templates

    The STL and professional C++

    • Algorithms and lambdas
    • Exceptions
    • Recursion
    • Project: a grade book
    C++

    Classes and OOP · Lesson 16 of 21

    Inheritance and virtual functions

    One class building on another, polymorphism, and why destructors must be virtual.

    12 minutes2 games

    class Quiz : public Lesson means Quiz gets everything in Lesson and adds more. The real power is polymorphism: a pointer or reference of the parent type can refer to any child, and calling a virtual function runs the version of the actual type.

    C++
    #include <iostream>
    #include <memory>
    #include <string>
    #include <vector>
    
    class Lesson {
    public:
        explicit Lesson(std::string title) : title_(std::move(title)) {}
        virtual ~Lesson() = default;
        virtual int minutes() const = 0;            // pure virtual: every lesson must say
        std::string describe() const { return title_ + " (" + std::to_string(minutes()) + " min)"; }
    protected:
        std::string title_;
    };
    
    class Video : public Lesson {
    public:
        Video(std::string t, int seconds) : Lesson(std::move(t)), seconds_(seconds) {}
        int minutes() const override { return (seconds_ + 59) / 60; }
    private:
        int seconds_;
    };
    
    class Quiz : public Lesson {
    public:
        Quiz(std::string t, int questions) : Lesson(std::move(t)), questions_(questions) {}
        int minutes() const override { return questions_ * 2; }
    private:
        int questions_;
    };
    
    int main() {
        std::vector<std::unique_ptr<Lesson>> course;
        course.push_back(std::make_unique<Video>("Pointers", 610));
        course.push_back(std::make_unique<Quiz>("Pointers quiz", 5));
    
        int total = 0;
        for (const auto& l : course) {
            std::cout << l->describe() << "\n";
            total += l->minutes();
        }
        std::cout << "total " << total << " min\n";
        return 0;
    }
    • Lesson (abstract)
      • virtual int minutes() const = 0
      • Video : minutes() = ceil(seconds / 60)
      • Quiz : minutes() = questions × 2

    describe() is written once in the parent, yet each child reports its own time.

    • virtual in the parent lets children replace the function.
    • override in the child makes the compiler check you're really replacing one (a typo in the name or const is reported).
    • = 0 makes the function pure virtual and the class abstract: you can't create one, only inherit from it.

    Important

    Any class that's inherited from and deleted through a parent pointer needs a virtual destructor. Without it, deleting through a Lesson* runs only the parent's destructor and the child's parts are never cleaned up (undefined behavior).

    What's the output?

    #include <iostream>
    struct A {
        void hi() const { std::cout << "A"; }
        virtual void bye() const { std::cout << "a"; }
        virtual ~A() = default;
    };
    struct B : A {
        void hi() const { std::cout << "B"; }
        void bye() const override { std::cout << "b"; }
    };
    int main() {
        B b;
        const A& r = b;
        r.hi();
        r.bye();
        std::cout << "\n";
    }

    What will this code print?

    Interview question

    How do virtual functions work under the hood? (vtable)

    Exercise

    Finish Circle and Square so each overrides area(). The program must print 28.26 then 16.

    Expected output:
    28.26
    16
    C++
    #include <iostream>
    #include <memory>
    #include <vector>
    
    struct Shape {
        virtual ~Shape() = default;
        virtual double area() const = 0;
    };
    
    struct Circle : Shape {
        double r;
        explicit Circle(double radius) : r(radius) {}
    };
    
    struct Square : Shape {
        double side;
        explicit Square(double s) : side(s) {}
    };
    
    int main() {
        std::vector<std::unique_ptr<Shape>> shapes;
        shapes.push_back(std::make_unique<Circle>(3));
        shapes.push_back(std::make_unique<Square>(4));
        for (const auto& s : shapes) std::cout << s->area() << "\n";
        return 0;
    }

    Learn more from

    • learncpp: Virtual functions and polymorphismlearncpp.com
    • learncpp: Virtual destructorslearncpp.com
    • cppreference: virtual function specifieren.cppreference.com
    • isocpp FAQ: Inheritance and virtual functionsisocpp.org

    Played 0 of 2 games

    Sign in to save your progress and earn XP.

    PreviousConstructors and destructorsNextTemplates
    SeaCode

    Learn to code for real, online or at our branch in front of Cairo University, Giza.

    Learn

    • All courses
    • Interactive tutorials
    • Interview practice problems
    • Mock interview
    • Learning tracks
    • Code Arena
    • Workshops & Events
    • Knowledge library
    • Team projects

    Your account

    • Log in
    • Sign up
    • Learning plan
    • Certificates
    • Site map

    Contact us

    • WhatsApp
    • 010 9094 1104
    • In front of Cairo University, Giza

    © 2026 SeaCode. All rights reserved.