📘 Learning Objectives
After completing this chapter, you will: - Master advanced inheritance patterns and techniques - Understand virtual inheritance and diamond problem resolution - Learn about abstract base classes and pure virtual functions - Master multiple inheritance and interface segregation - Understand runtime type information (RTTI) and dynamic casting
🎯 Key Concepts
1. Virtual Inheritance
- Diamond inheritance problem: Multiple inheritance ambiguity
- Virtual base classes: Shared base class instances
- Virtual inheritance syntax: virtual keyword in inheritance
- Constructor initialization: Virtual base constructor order
- Memory layout: Virtual base class memory organization
2. Abstract Base Classes
- Pure virtual functions: Functions without implementation
- Abstract classes: Classes that cannot be instantiated
- Interface design: Pure virtual function interfaces
- Implementation inheritance: Concrete derived classes
- Virtual destructors: Proper cleanup in inheritance hierarchies
3. Multiple Inheritance
- Multiple base classes: Inheriting from multiple classes
- Name resolution: Ambiguous function resolution
- Virtual inheritance: Solving diamond inheritance
- Interface segregation: Multiple interface inheritance
- Composition vs inheritance: When to use each approach
4. Runtime Type Information (RTTI)
- typeid operator: Runtime type identification
- dynamic_cast: Safe downcasting
- Virtual function tables: RTTI implementation
- Type safety: Runtime type checking
- Performance considerations: RTTI overhead
5. Advanced Polymorphism
- Virtual function overriding: Proper override syntax
- Covariant return types: Derived class return types
- Virtual function tables: VTable implementation
- Virtual inheritance: Virtual base class handling
- Performance optimization: Virtual function calls
🧩 Practice Exercises
Exercise 20.1: Virtual Inheritance
Implement a diamond inheritance hierarchy with virtual inheritance.
Exercise 20.2: Abstract Base Classes
Create abstract base classes with pure virtual functions.
Exercise 20.3: Multiple Inheritance
Use multiple inheritance to create complex class hierarchies.
Exercise 20.4: RTTI and Dynamic Casting
Use RTTI for safe type conversions and runtime type checking.
💻 Code Examples
Virtual Inheritance
#include <iostream>
#include <string>
class Animal {
protected:
std::string name;
public:
Animal(const std::string& n) : name(n) {}
virtual ~Animal() = default;
virtual void makeSound() = 0;
virtual void eat() = 0;
};
class Mammal : public virtual Animal {
public:
Mammal(const std::string& n) : Animal(n) {}
void breathe() { std::cout << name << " breathes with lungs" << std::endl; }
};
class WingedAnimal : public virtual Animal {
public:
WingedAnimal(const std::string& n) : Animal(n) {}
void fly() { std::cout << name << " can fly" << std::endl; }
};
class Bat : public Mammal, public WingedAnimal {
public:
Bat(const std::string& n) : Animal(n), Mammal(n), WingedAnimal(n) {}
void makeSound() override { std::cout << name << " makes bat sounds" << std::endl; }
void eat() override { std::cout << name << " eats insects" << std::endl; }
};
int main() {
Bat bat("Vampire Bat");
bat.makeSound();
bat.eat();
bat.breathe();
bat.fly();
return 0;
}
Abstract Base Classes
#include <iostream>
#include <vector>
#include <memory>
class Shape {
public:
virtual ~Shape() = default;
virtual double area() const = 0;
virtual double perimeter() const = 0;
virtual void draw() const = 0;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double area() const override { return 3.14159 * radius * radius; }
double perimeter() const override { return 2 * 3.14159 * radius; }
void draw() const override { std::cout << "Drawing a circle" << std::endl; }
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() const override { return width * height; }
double perimeter() const override { return 2 * (width + height); }
void draw() const override { std::cout << "Drawing a rectangle" << std::endl; }
};
int main() {
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Circle>(5.0));
shapes.push_back(std::make_unique<Rectangle>(4.0, 6.0));
for (const auto& shape : shapes) {
std::cout << "Area: " << shape->area() << std::endl;
std::cout << "Perimeter: " << shape->perimeter() << std::endl;
shape->draw();
}
return 0;
}
🎓 Key Takeaways
- Use virtual inheritance to solve diamond inheritance problems
- Design abstract base classes with pure virtual functions
- Be careful with multiple inheritance - prefer composition when possible
- Use RTTI judiciously - it has performance overhead
- Always use virtual destructors in inheritance hierarchies
🔗 Next Steps
After mastering advanced inheritance, proceed to Chapter 21 to learn about advanced polymorphism.
📚 Additional Resources
- C++ Reference: Virtual Inheritance
- C++ Core Guidelines: Inheritance
- Practice with complex inheritance hierarchies