CodeNebula
C++98corebeginner

Inheritance

C++98 · The Foundation · Compiler flag: -std=c++98

Explanation

A class inherits properties from one base class.

Real-World Scenario

A `SportsCar` class inherits from a `Car` class in a vehicle simulation.

Quick Snippet

snippet.cpp
class Car {}; class SportsCar : public Car {};

Full Example

single_inheritance.cpp
// CodeNebula - C++98 Example: Single Inheritance
// Compile: g++ -std=c++98 -Wall -Wextra -o example single_inheritance.cpp
//
// This example demonstrates:
// - Deriving a class from a single base class
// - Constructor chaining (base constructed before derived)
// - Destructor order (derived destroyed before base)
// - Member access: inherited public/protected members
// - Method overriding (non-virtual, to show hiding)
// - Using base-class functionality in derived class

#include <iostream>
#include <cstring>
#include <cstdio>

// ============================================================
// Base class: Animal
// ============================================================
class Animal {
private:
    char name[64];
    int  age;

protected:
    // Protected: accessible by derived classes, not by outsiders
    int legs;

public:
    // Constructor
    Animal(const char* n, int a, int l) : age(a), legs(l) {
        std::strncpy(name, n, 63);
        name[63] = '\0';
        std::cout << "  Animal constructor: " << name << std::endl;
    }

    // Destructor
    ~Animal() {
        std::cout << "  Animal destructor: " << name << std::endl;
    }

    // Public accessors
    const char* getName() const { return name; }
    int getAge() const { return age; }

    // A method that derived classes may override (non-virtual here)
    void speak() const {
        std::cout << "  " << name << " says: ..." << std::endl;
    }

    void describe() const {
        std::cout << "  Name: " << name
                  << ", Age: " << age
                  << ", Legs: " << legs << std::endl;
    }
};

// ============================================================
// Derived class: Dog (inherits from Animal)
// ============================================================
class Dog : public Animal {
private:
    char breed[64];

public:
    // Derived constructor calls base constructor in initialiser list
    Dog(const char* n, int a, const char* b)
        : Animal(n, a, 4)   // <-- base constructor called first
    {
        std::strncpy(breed, b, 63);
        breed[63] = '\0';
        std::cout << "  Dog constructor: " << getName()
                  << " (" << breed << ")" << std::endl;
    }

    ~Dog() {
        std::cout << "  Dog destructor: " << getName() << std::endl;
    }

    // Override speak (hides base version -- not virtual dispatch)
    void speak() const {
        std::cout << "  " << getName() << " says: Woof! Woof!" << std::endl;
    }

    void fetch() const {
        std::cout << "  " << getName() << " fetches the ball!" << std::endl;
    }

    void describeBreed() const {
        std::cout << "  Breed: " << breed << std::endl;
        // 'legs' is accessible because it is protected in Animal
        std::cout << "  Legs (from base): " << legs << std::endl;
    }
};

// ============================================================
// Derived class: Snake (inherits from Animal)
// ============================================================
class Snake : public Animal {
private:
    double lengthMeters;

public:
    Snake(const char* n, int a, double len)
        : Animal(n, a, 0), lengthMeters(len)
    {
        std::cout << "  Snake constructor: " << getName() << std::endl;
    }

    ~Snake() {
        std::cout << "  Snake destructor: " << getName() << std::endl;
    }

    void speak() const {
        std::cout << "  " << getName() << " says: Hissss!" << std::endl;
    }

    void describeLength() const {
        std::cout << "  Length: " << lengthMeters << " meters" << std::endl;
    }
};

int main() {
    std::cout << "========================================" << std::endl;
    std::cout << "1. CONSTRUCTOR CHAINING" << std::endl;
    std::cout << "========================================" << std::endl;
    std::cout << "  (Base Animal is constructed BEFORE derived Dog)\n" << std::endl;
    {
        Dog rex("Rex", 5, "German Shepherd");
        std::cout << std::endl;
    }
    std::cout << "  (Dog destroyed BEFORE Animal -- reverse order)\n" << std::endl;

    std::cout << "========================================" << std::endl;
    std::cout << "2. INHERITED MEMBERS" << std::endl;
    std::cout << "========================================" << std::endl;
    {
        Dog buddy("Buddy", 3, "Labrador");
        std::cout << std::endl;

        // Using inherited public method
        buddy.describe();

        // Using derived-specific methods
        buddy.describeBreed();
        buddy.fetch();
        std::cout << std::endl;
    }

    std::cout << "\n========================================" << std::endl;
    std::cout << "3. METHOD OVERRIDING (non-virtual)" << std::endl;
    std::cout << "========================================" << std::endl;
    {
        Dog   d("Max", 4, "Poodle");
        Snake s("Kaa", 8, 3.5);
        std::cout << std::endl;

        // Calls Dog::speak() -- hides Animal::speak()
        d.speak();

        // Calls Snake::speak()
        s.speak();

        // Can still call base version explicitly
        std::cout << "\n  Calling Animal::speak() explicitly on Dog:" << std::endl;
        d.Animal::speak();

        std::cout << std::endl;
    }

    std::cout << "\n========================================" << std::endl;
    std::cout << "4. USING BASE POINTER (no virtual -- static dispatch)" << std::endl;
    std::cout << "========================================" << std::endl;
    {
        Dog d("Fido", 2, "Beagle");
        std::cout << std::endl;

        Animal* aPtr = &d;  // base pointer to derived object

        // This calls Animal::speak(), NOT Dog::speak()
        // because speak() is not virtual
        aPtr->speak();
        std::cout << "  (Called Animal::speak() -- no virtual dispatch)" << std::endl;

        // Inherited public methods work fine
        aPtr->describe();
        std::cout << std::endl;
    }

    std::cout << "\n========================================" << std::endl;
    std::cout << "5. MULTIPLE DERIVED OBJECTS" << std::endl;
    std::cout << "========================================" << std::endl;
    {
        Dog   d("Lucky", 6, "Dalmatian");
        Snake s("Naga", 12, 4.2);
        std::cout << std::endl;

        d.describe();
        d.describeBreed();
        d.speak();

        std::cout << std::endl;

        s.describe();
        s.describeLength();
        s.speak();
        std::cout << std::endl;
    }

    return 0;
}

// Expected output:
// ========================================
// 1. CONSTRUCTOR CHAINING
// ========================================
//   (Base Animal is constructed BEFORE derived Dog)
//
//   Animal constructor: Rex
//   Dog constructor: Rex (German Shepherd)
//
//   Dog destructor: Rex
//   Animal destructor: Rex
//   (Dog destroyed BEFORE Animal -- reverse order)
//
// ========================================
// 2. INHERITED MEMBERS
// ========================================
//   Animal constructor: Buddy
//   Dog constructor: Buddy (Labrador)
//
//   Name: Buddy, Age: 3, Legs: 4
//   Breed: Labrador
//   Legs (from base): 4
//   Buddy fetches the ball!
//
//   Dog destructor: Buddy
//   Animal destructor: Buddy
//
// ========================================
// 3. METHOD OVERRIDING (non-virtual)
// ========================================
//   ...constructor output...
//   Max says: Woof! Woof!
//   Kaa says: Hissss!
//   Calling Animal::speak() explicitly on Dog:
//   Max says: ...
//   ...destructor output...
//
// ========================================
// 4. USING BASE POINTER (no virtual -- static dispatch)
// ========================================
//   ...constructor output...
//   Fido says: ...
//   (Called Animal::speak() -- no virtual dispatch)
//   Name: Fido, Age: 2, Legs: 4
//   ...destructor output...
//
// ========================================
// 5. MULTIPLE DERIVED OBJECTS
// ========================================
//   ...object descriptions...
Run command
g++ -std=c++98 -Wall -Wextra -o example single_inheritance.cpp