1. Basic Concepts of Inheritance
1.1 What is Inheritance?
Inheritance is a mechanism where a class (derived/child class) can inherit properties and methods from another class (base/parent class).
Real-World Analogy: Think of inheritance like family traits:
- A child inherits characteristics from parents (eye color, height)
- The child can also have unique characteristics
- The child can modify inherited traits (different hairstyle)
Benefits of Inheritance:
- Code Reusability: Write once, use in multiple classes
- Logical Hierarchy: Represents real-world relationships
- Easier Maintenance: Changes in base class automatically reflect in derived classes
- Polymorphism: Enables treating derived objects as base objects
1.2 Basic Syntax
// Base class (Parent)
class BaseClass {
// members
};
// Derived class (Child)
class DerivedClass : access_specifier BaseClass {
// additional members
};
Example:
#include <iostream>
#include <string>
using namespace std;
// Base class
class Animal {
protected:
string name;
int age;
public:
Animal(string n, int a) : name(n), age(a) {
cout << "Animal constructor called" << 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
class Dog : public Animal {
private:
string breed;
public:
Dog(string n, int a, string b) : Animal(n, a), breed(b) {
cout << "Dog constructor called" << endl;
}
void bark() {
cout << name << " is barking: Woof! Woof!" << endl;
}
void displayDogInfo() {
displayInfo(); // Inherited method
cout << "Breed: " << breed << endl;
}
};
int main() {
Dog myDog("Buddy", 3, "Golden Retriever");
// Using inherited methods
myDog.eat();
myDog.sleep();
// Using derived class method
myDog.bark();
myDog.displayDogInfo();
return 0;
}
Output:
Animal constructor called
Dog constructor called
Buddy is eating...
Buddy is sleeping...
Buddy is barking: Woof! Woof!
Name: Buddy, Age: 3
Breed: Golden Retriever
1.3 Access Specifiers in Inheritance
Three Types of Inheritance:
| Base Class Member | public Inheritance | protected Inheritance | private Inheritance |
|---|---|---|---|
| public members | public | protected | private |
| protected members | protected | protected | private |
| private members | Not accessible | Not accessible | Not accessible |
Example:
#include <iostream>
using namespace std;
class Base {
private:
int privateVar;
protected:
int protectedVar;
public:
int publicVar;
Base() : privateVar(1), protectedVar(2), publicVar(3) {}
};
// Public Inheritance
class PublicDerived : public Base {
public:
void access() {
// privateVar = 10; // ERROR: private not accessible
protectedVar = 20; // OK: protected -> protected
publicVar = 30; // OK: public -> public
}
};
// Protected Inheritance
class ProtectedDerived : protected Base {
public:
void access() {
// privateVar = 10; // ERROR: private not accessible
protectedVar = 20; // OK: protected -> protected
publicVar = 30; // OK: public -> protected
}
};
// Private Inheritance
class PrivateDerived : private Base {
public:
void access() {
// privateVar = 10; // ERROR: private not accessible
protectedVar = 20; // OK: protected -> private
publicVar = 30; // OK: public -> private
}
};
int main() {
PublicDerived pub;
pub.publicVar = 100; // OK: public member accessible
// pub.protectedVar = 200; // ERROR: protected not accessible outside
ProtectedDerived prot;
// prot.publicVar = 100; // ERROR: public became protected
PrivateDerived priv;
// priv.publicVar = 100; // ERROR: public became private
return 0;
}
Best Practice: Use public inheritance for most cases (is-a relationship).
1.4 Constructor and Destructor in Inheritance
Execution Order:
- Construction: Base class constructor → Derived class constructor
- Destruction: Derived class destructor → Base class destructor
#include <iostream>
#include <string>
using namespace std;
class Vehicle {
protected:
string brand;
public:
Vehicle(string b) : brand(b) {
cout << "Vehicle constructor: " << brand << endl;
}
~Vehicle() {
cout << "Vehicle destructor: " << brand << endl;
}
};
class Car : public Vehicle {
private:
string model;
public:
Car(string b, string m) : Vehicle(b), model(m) {
cout << "Car constructor: " << model << endl;
}
~Car() {
cout << "Car destructor: " << model << endl;
}
};
class ElectricCar : public Car {
private:
int batteryCapacity;
public:
ElectricCar(string b, string m, int battery)
: Car(b, m), batteryCapacity(battery) {
cout << "ElectricCar constructor: " << batteryCapacity << " kWh" << endl;
}
~ElectricCar() {
cout << "ElectricCar destructor: " << batteryCapacity << " kWh" << endl;
}
};
int main() {
cout << "=== Creating ElectricCar ===" << endl;
ElectricCar tesla("Tesla", "Model 3", 75);
cout << "\n=== Destroying ElectricCar ===" << endl;
// Destructor called automatically when going out of scope
return 0;
}
Output:
=== Creating ElectricCar ===
Vehicle constructor: Tesla
Car constructor: Model 3
ElectricCar constructor: 75 kWh
=== Destroying ElectricCar ===
ElectricCar destructor: 75 kWh
Car destructor: Model 3
Vehicle destructor: Tesla
1.5 Practical Example: Employee Hierarchy
#include <iostream>
#include <string>
using namespace std;
class Employee {
protected:
string name;
int id;
double baseSalary;
public:
Employee(string n, int i, double salary)
: name(n), id(i), baseSalary(salary) {}
void displayBasicInfo() {
cout << "Name: " << name << endl;
cout << "ID: " << id << endl;
cout << "Base Salary: $" << baseSalary << endl;
}
void work() {
cout << name << " is working..." << endl;
}
virtual double calculateSalary() {
return baseSalary;
}
};
class Manager : public Employee {
private:
double bonus;
int teamSize;
public:
Manager(string n, int i, double salary, double b, int team)
: Employee(n, i, salary), bonus(b), teamSize(team) {}
void displayManagerInfo() {
displayBasicInfo();
cout << "Bonus: $" << bonus << endl;
cout << "Team Size: " << teamSize << endl;
}
void conductMeeting() {
cout << name << " is conducting a meeting..." << endl;
}
double calculateSalary() override {
return baseSalary + bonus;
}
};
class Developer : public Employee {
private:
string programmingLanguage;
int projectsCompleted;
public:
Developer(string n, int i, double salary, string lang, int projects)
: Employee(n, i, salary), programmingLanguage(lang),
projectsCompleted(projects) {}
void displayDeveloperInfo() {
displayBasicInfo();
cout << "Programming Language: " << programmingLanguage << endl;
cout << "Projects Completed: " << projectsCompleted << endl;
}
void writeCode() {
cout << name << " is writing " << programmingLanguage << " code..." << endl;
}
double calculateSalary() override {
return baseSalary + (projectsCompleted * 500);
}
};
int main() {
Manager mgr("Alice Johnson", 101, 8000, 2000, 10);
Developer dev("Bob Smith", 102, 6000, "C++", 5);
cout << "=== Manager Information ===" << endl;
mgr.displayManagerInfo();
mgr.work(); // Inherited
mgr.conductMeeting(); // Own method
cout << "Total Salary: $" << mgr.calculateSalary() << endl;
cout << "\n=== Developer Information ===" << endl;
dev.displayDeveloperInfo();
dev.work(); // Inherited
dev.writeCode(); // Own method
cout << "Total Salary: $" << dev.calculateSalary() << endl;
return 0;
}
No comments to display
No comments to display