Inheritance — Base & Derived Classes
class Dog : public Animal), what a derived class actually inherits, how constructor chaining works, and what protected access is for.
What Problem Does Inheritance Solve?
Imagine you're modelling animals in a program: a Dog and a Cat both have a name and an age, and both can eat() and sleep(). Without inheritance, you'd copy-paste that code into every animal class — and if you ever needed to fix a bug in eat(), you'd have to fix it everywhere.
Inheritance lets one class (the derived class) automatically reuse the member variables and member functions of another class (the base class), and then add or specialize what makes it unique. It models an "is-a" relationship: a Dog is an Animal, a Cat is an Animal.
Animal. Also called the "parent" or "superclass."Dog. Also called the "child" or "subclass."Base & Derived Class Syntax
To derive a new class, write a colon after the class name followed by an access level (almost always public) and the base class name: class Dog : public Animal. Every Dog object now automatically has everything a plain Animal has, plus whatever Dog adds.
class Animal { protected: string name; int age; public: Animal(string n, int a) { name = n; age = a; } void eat() { cout << name << " is eating." << endl; } }; // Dog "is-a" Animal — inherits name, age, eat() class Dog : public Animal { public: Dog(string n, int a) : Animal(n, a) {} void bark() { cout << name << " says: Woof!" << endl; // name is inherited } };
What Gets Inherited — and protected Access
A derived class inherits all member variables and member functions of its base class (except constructors and destructors, which have their own rules). But inherited does not always mean directly accessible — access still follows the specifiers:
public membersprotected membersprivate membersname and age are protected specifically so that Dog::bark() can read name directly. If they were private, Dog would need to go through a public getter on Animal instead.Constructor Chaining
A derived class doesn't automatically know how to initialize the base class's members — you must explicitly call a base class constructor, using an initializer list in the derived constructor. The base constructor always finishes running before the derived constructor's own body executes.
class Cat : public Animal { public: // ": Animal(n, a)" calls the Animal constructor FIRST Cat(string n, int a) : Animal(n, a) { // this body runs AFTER Animal's constructor has finished } void meow() { cout << name << " says: Meow!" << endl; } };
Animal has no default (no-argument) constructor, and Cat's constructor doesn't explicitly call Animal(n, a) in its initializer list, the compiler has no way to build the Animal part of the object — you'll get a compile error.Complete Worked Example — Animal, Dog & Cat
Putting it all together: one base class, two derived classes, each reusing shared behaviour while adding their own.
#include <iostream> #include <string> using namespace std; class Animal { protected: string name; int age; public: Animal(string n, int a) { name = n; age = a; } void eat() { cout << name << " is eating." << endl; } void sleep() { cout << name << " is sleeping." << endl; } }; class Dog : public Animal { public: Dog(string n, int a) : Animal(n, a) {} void bark() { cout << name << " says: Woof!" << endl; } }; class Cat : public Animal { public: Cat(string n, int a) : Animal(n, a) {} void meow() { cout << name << " says: Meow!" << endl; } }; int main() { Dog d("Rex", 3); Cat c("Whiskers", 2); d.eat(); // inherited from Animal d.bark(); // defined in Dog c.sleep(); // inherited from Animal c.meow(); // defined in Cat return 0; }
Output:
Rex is eating. Rex says: Woof! Whiskers is sleeping. Whiskers says: Meow!
Lesson Summary
class Dog : public Animal { ... };protected members are visible to derived classes but hidden from outside code — a middle ground between public and private.Dog(n, a) : Animal(n, a) {}.class Dog : public Animal, which class is the derived class?protected members treated?Dog object is created, which constructor runs first?Now it's your turn to extend a class hierarchy. Complete the challenge below in any C++ compiler or online IDE.
Bird class 🐦Using the
Animal base class from Section 5 (with protected name and age, and public eat()/sleep()), create a new derived class Bird : public Animal that:
1. Has a constructor that chains to
Animal's constructor.2. Adds a new method
fly() that prints "<name> is flying!".3. In
main(), create a Bird object and call eat(), sleep(), and fly() on it.
💡 Show hints if you're stuck
- Header:
class Bird : public Animal { - Constructor:
Bird(string n, int a) : Animal(n, a) {} fly()can usenamedirectly since it'sprotected, notprivate- You don't need to rewrite
eat()orsleep()— they come for free through inheritance