Inheritance is like a family tree - children inherit traits from their parents. In programming, classes can inherit properties and behaviors from other classes. A "Car" is a type of "Vehicle", a "Dog" is a type of "Animal"!
// Base class (Parent)
class Animal {
protected: // Accessible to derived classes
string name;
int age;
public:
Animal(string n, int a) : name(n), age(a) {
cout << "Animal constructor" << endl;
}
void eat() {
cout << name << " is eating." << endl;
}
void sleep() {
cout << name << " is sleeping." << endl;
}
void displayInfo() {
cout << "Name: " << name << ", Age: " << age << endl;
}
};
// Derived class (Child)
class Dog : public Animal { // Public inheritance
private:
string breed;
public:
// Constructor calls base constructor
Dog(string n, int a, string b) : Animal(n, a), breed(b) {
cout << "Dog constructor" << endl;
}
// Additional method
void bark() {
cout << name << " says: Woof! Woof!" << endl;
}
// Can access protected members
void wagTail() {
cout << name << " is wagging tail happily!" << endl;
}
void displayInfo() {
Animal::displayInfo(); // Call base version
cout << "Breed: " << breed << endl;
}
};
// Usage
int main() {
Dog myDog("Buddy", 3, "Golden Retriever");
myDog.eat(); // Inherited from Animal
myDog.sleep(); // Inherited from Animal
myDog.bark(); // Dog's own method
myDog.displayInfo(); // Overridden method
return 0;
}
Think of access levels like security clearance - some information is public, some is classified for family only (protected), and some is top secret (private)!
Construction is like building a house - foundation first (base), then walls (derived). Destruction is the reverse - tear down walls first, then foundation!
Polymorphism means "many forms" - like how a remote control's "play" button works for DVD players, streaming devices, and game consoles. One interface, multiple implementations!
Virtual functions are like job descriptions - the base class says "here's what needs to be done" and derived classes say "here's how I do it"!
class Shape {
protected:
string color;
public:
Shape(string c = "black") : color(c) {}
// Virtual functions - can be overridden
virtual void draw() {
cout << "Drawing a shape" << endl;
}
virtual double area() {
return 0; // Default implementation
}
// Non-virtual function
void setColor(string c) {
color = c;
}
// Virtual destructor - important!
virtual ~Shape() {
cout << "Shape destructor" << endl;
}
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r, string c = "black") : Shape(c), radius(r) {}
// Override virtual functions
void draw() override { // 'override' keyword for safety
cout << "Drawing a " << color << " circle with radius " << radius << endl;
}
double area() override {
return 3.14159 * radius * radius;
}
~Circle() {
cout << "Circle destructor" << endl;
}
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h, string c = "black")
: Shape(c), width(w), height(h) {}
void draw() override {
cout << "Drawing a " << color << " rectangle "
<< width << "x" << height << endl;
}
double area() override {
return width * height;
}
};
// Polymorphism in action!
void processShape(Shape* shape) {
shape->draw();
cout << "Area: " << shape->area() << endl;
cout << "---" << endl;
}
int main() {
// Array of different shapes
Shape* shapes[3];
shapes[0] = new Circle(5, "red");
shapes[1] = new Rectangle(4, 6, "blue");
shapes[2] = new Circle(3, "green");
// Process all shapes polymorphically
for (int i = 0; i < 3; i++) {
processShape(shapes[i]);
}
// Clean up
for (int i = 0; i < 3; i++) {
delete shapes[i]; // Calls correct destructor!
}
return 0;
}
Abstract classes are like contracts - they define what must be done but not how. You can't build a generic "Vehicle", but you can build a "Car" or "Bike"!
// Abstract base class
class GameCharacter {
protected:
string name;
int health;
int level;
public:
GameCharacter(string n, int h, int l)
: name(n), health(h), level(l) {}
// Pure virtual functions - MUST be implemented by derived classes
virtual void attack() = 0;
virtual void defend() = 0;
virtual void specialAbility() = 0;
// Regular virtual function - CAN be overridden
virtual void takeDamage(int damage) {
health -= damage;
if (health < 0) health = 0;
cout << name << " takes " << damage << " damage!" << endl;
}
// Non-virtual functions
void displayStats() {
cout << "=== " << name << " ===" << endl;
cout << "Level: " << level << endl;
cout << "Health: " << health << endl;
}
virtual ~GameCharacter() {}
};
// Concrete derived class
class Warrior : public GameCharacter {
private:
int armor;
public:
Warrior(string n) : GameCharacter(n, 100, 1), armor(50) {}
void attack() override {
cout << name << " swings sword for heavy damage!" << endl;
}
void defend() override {
cout << name << " raises shield, reducing damage by "
<< armor << "%!" << endl;
}
void specialAbility() override {
cout << name << " enters RAGE mode! Attack doubled!" << endl;
}
void takeDamage(int damage) override {
int reducedDamage = damage * (100 - armor) / 100;
GameCharacter::takeDamage(reducedDamage);
}
};
class Mage : public GameCharacter {
private:
int mana;
public:
Mage(string n) : GameCharacter(n, 70, 1), mana(100) {}
void attack() override {
if (mana >= 10) {
cout << name << " casts fireball!" << endl;
mana -= 10;
} else {
cout << name << " is out of mana!" << endl;
}
}
void defend() override {
cout << name << " casts magic shield!" << endl;
}
void specialAbility() override {
cout << name << " summons meteor shower!" << endl;
mana = 0; // Uses all mana
}
};
Multiple inheritance is like having multiple parents - it can get complicated! The diamond problem occurs when a class inherits from two classes that share a common base.
Dynamic casting is like checking someone's ID - you want to make sure they really are who they claim to be before giving them special access!
class Employee {
protected:
string name;
int id;
public:
Employee(string n, int i) : name(n), id(i) {}
virtual void work() {
cout << name << " is working." << endl;
}
virtual ~Employee() {}
};
class Manager : public Employee {
private:
vector team;
public:
Manager(string n, int i) : Employee(n, i) {}
void work() override {
cout << name << " is managing the team." << endl;
}
void conductMeeting() {
cout << name << " is conducting a meeting." << endl;
}
void addTeamMember(Employee* emp) {
team.push_back(emp);
}
};
class Developer : public Employee {
private:
string programmingLanguage;
public:
Developer(string n, int i, string lang)
: Employee(n, i), programmingLanguage(lang) {}
void work() override {
cout << name << " is coding in " << programmingLanguage << endl;
}
void debug() {
cout << name << " is debugging code." << endl;
}
};
// Using dynamic_cast
void processEmployee(Employee* emp) {
emp->work(); // Polymorphic call
// Try to cast to Manager
Manager* mgr = dynamic_cast(emp);
if (mgr != nullptr) {
mgr->conductMeeting(); // Manager-specific method
}
// Try to cast to Developer
Developer* dev = dynamic_cast(emp);
if (dev != nullptr) {
dev->debug(); // Developer-specific method
}
}
Create a zoo management system using inheritance and polymorphism:
class Animal {
protected:
string name;
int age;
double weight;
public:
Animal(string n, int a, double w)
: name(n), age(a), weight(w) {}
// Pure virtual functions
virtual void makeSound() = 0;
virtual void eat() = 0;
virtual string getHabitat() = 0;
// TODO: Add more virtual functions
virtual ~Animal() {}
};
class Mammal : public Animal {
// TODO: Implement mammal-specific behavior
};
class Bird : public Animal {
private:
double wingspan;
// TODO: Implement bird-specific behavior
};
class Zoo {
private:
vector animals;
public:
void addAnimal(Animal* animal);
void feedAllAnimals();
void conductTour();
// TODO: Complete implementation
};
Behind the scenes, C++ uses a virtual function table - like a phone directory that tells the program which function to call!
Build a simple game engine framework:
class GameObject {
protected:
float x, y;
bool visible;
public:
virtual void render() = 0;
virtual ~GameObject() {}
};
class Updateable {
public:
virtual void update(float deltaTime) = 0;
};
class Collidable {
public:
virtual bool checkCollision(Collidable* other) = 0;
virtual void onCollision(Collidable* other) = 0;
};
class Player : public GameObject,
public Updateable,
public Collidable {
// Multiple inheritance!
};