SyntaxStudy
Sign Up
C++ Single Inheritance and Base Class Constructors
C++ Beginner 1 min read

Single Inheritance and Base Class Constructors

Inheritance allows a derived class to acquire the data members and member functions of a base class, forming an 'is-a' relationship. In C++, a class inherits using the colon syntax followed by an access specifier — 'public', 'protected', or 'private'. Public inheritance is the most common and models true subtyping: a pointer or reference to the base class can refer to any object of a derived class. When a derived object is constructed, the base class constructor always runs first. The derived class passes arguments to the base constructor through its member initialiser list using the base class name. If no explicit base constructor is invoked, the compiler calls the default constructor. Forgetting to call the correct base constructor is a common source of bugs in hierarchies. Base class destructors should be declared 'virtual' whenever the class is intended to be used polymorphically. Without a virtual destructor, deleting a derived object through a base pointer invokes only the base destructor, leaking resources owned by the derived part. This is one of the most important rules in C++ class design.
Example
#include <iostream>
#include <string>

// Base class
class Animal {
public:
    explicit Animal(const std::string& name, int age)
        : name_(name), age_(age) {
        std::cout << "Animal constructed: " << name_ << "\n";
    }

    // Virtual destructor — essential for polymorphic use
    virtual ~Animal() {
        std::cout << "Animal destroyed: " << name_ << "\n";
    }

    std::string name() const { return name_; }
    int         age()  const { return age_;  }

    virtual void speak() const {
        std::cout << name_ << " makes a sound.\n";
    }

protected:
    std::string name_;
    int         age_;
};

// Derived class
class Dog : public Animal {
public:
    Dog(const std::string& name, int age, const std::string& breed)
        : Animal(name, age)   // call base constructor explicitly
        , breed_(breed)
    {
        std::cout << "Dog constructed: " << breed_ << "\n";
    }

    ~Dog() override {
        std::cout << "Dog destroyed: " << name_ << "\n";
    }

    void speak() const override {
        std::cout << name_ << " barks!\n";
    }

    std::string breed() const { return breed_; }

private:
    std::string breed_;
};

int main() {
    Animal* a = new Dog("Rex", 3, "Labrador");
    a->speak();
    std::cout << "Breed: " << static_cast<Dog*>(a)->breed() << "\n";
    delete a;   // calls Dog::~Dog then Animal::~Animal (virtual)
    return 0;
}