Week 6 OOP theory
Inheritance (Continued)
Let's continue exploring the different types of inheritance in C++:
3. Multilevel Inheritance
Definition: In multilevel inheritance, a derived class inherits from a base class, and then
another derived class inherits from that first derived class. This forms a chain of
inheritance.
"Is-a" Relationship (Transitive): Multilevel inheritance represents a transitive "is-a"
relationship. If class C inherits from class B, and class B inherits from class A, then class C
is a B, and since B is an A, class C is also an A.
Example (C++):
C++
#include <iostream>
#include <string>
// Base Class: Grandparent
class Animal {
public:
std::string name;
Animal(std::string n) : name(n) {
std::cout << "Animal constructed: " << name << std::endl;
}
void eat() {
std::cout << "Animal is eating." << std::endl;
}
~Animal() {
std::cout << "Animal destructed: " << name << std::endl;
}
};
// Derived Class 1: Mammal (inherits from Animal)
class Mammal : public Animal {
public:
Mammal(std::string n) : Animal(n) {
std::cout << "Mammal constructed: " << name << std::endl;
}
void breathe() {
std::cout << "Mammal is breathing." << std::endl;
}
~Mammal() {
std::cout << "Mammal destructed: " << name << std::endl;
}
};
// Derived Class 2: Dog (inherits from Mammal)
class Dog : public Mammal {
public:
Dog(std::string n) : Mammal(n) {
std::cout << "Dog constructed: " << name << std::endl;
}
void bark() {
std::cout << "Dog is barking." << std::endl;
}
~Dog() {
std::cout << "Dog destructed: " << name << std::endl;
}
};
int main() {
Dog myDog("Buddy");
[Link](); // Inherited from Animal
[Link](); // Inherited from Mammal
[Link](); // Specific to Dog
return 0;
}
Output of the Example:
Animal constructed: Buddy
Mammal constructed: Buddy
Dog constructed: Buddy
Animal is eating.
Mammal is breathing.
Dog is barking.
Dog destructed: Buddy
Mammal destructed: Buddy
Animal destructed: Buddy
In this example:
Animal is the base class.
Mammal inherits from Animal.
Dog inherits from Mammal.
Dog objects have access to the members of both Mammal and Animal.
4. Hierarchical Inheritance
Definition: In hierarchical inheritance, multiple derived classes inherit from a single base
class. This forms a tree-like structure or hierarchy.
"Is-a" Relationship (Multiple Specializations): Hierarchical inheritance represents
different specializations or types of the base class. For example, Cat is an Animal, and
Dog is an Animal.
Example (C++):
C++
#include <iostream>
#include <string>
// Base Class: Shape
class Shape {
public:
Shape(std::string n) : name(n) {
std::cout << "Shape constructed: " << name << std::endl;
}
void display() const {
std::cout << "Shape: " << name << std::endl;
}
virtual double area() const { // Virtual function for potential
overriding
return 0.0;
}
std::string name;
virtual ~Shape() {
std::cout << "Shape destructed: " << name << std::endl;
}
};
// Derived Class 1: Rectangle
class Rectangle : public Shape {
public:
Rectangle(double w, double h) : Shape("Rectangle"), width(w), height(h) {
std::cout << "Rectangle constructed." << std::endl;
}
double area() const override {
return width * height;
}
double width;
double height;
~Rectangle() {
std::cout << "Rectangle destructed." << std::endl;
}
};
// Derived Class 2: Circle
class Circle : public Shape {
public:
Circle(double r) : Shape("Circle"), radius(r) {
std::cout << "Circle constructed." << std::endl;
}
double area() const override {
return 3.14159 * radius * radius;
}
double radius;
~Circle() {
std::cout << "Circle destructed." << std::endl;
}
};
int main() {
Rectangle rect(5, 10);
[Link]();
std::cout << "Area of rectangle: " << [Link]() << std::endl;
Circle circ(7);
[Link]();
std::cout << "Area of circle: " << [Link]() << std::endl;
return 0;
}
Output of the Example:
Shape constructed: Rectangle
Rectangle constructed.
Shape: Rectangle
Area of rectangle: 50
Shape constructed: Circle
Circle constructed.
Shape: Circle
Area of circle: 153.937
Circle destructed.
Shape destructed: Circle
Rectangle destructed.
Shape destructed: Rectangle
In this example:
Shape is the base class.
Rectangle and Circle are derived classes that inherit from Shape.
Both Rectangle and Circle inherit the name and display() members from Shape and
provide their own specific implementations for area().
5. Hybrid Inheritance
Definition: Hybrid inheritance is a combination of two or more different types of
inheritance. For example, it can involve a combination of hierarchical and multiple
inheritance.
Complexity: Hybrid inheritance can lead to complex class hierarchies and potential
ambiguities (like the diamond problem) that need to be carefully managed using virtual
inheritance where necessary.
Conceptual Example (C++ - illustrating the idea):
C++
#include <iostream>
class A { public: void funcA() { std::cout << "Func A\n"; } };
class B : public A { public: void funcB() { std::cout << "Func B\n"; } };
class C : public A { public: void funcC() { std::cout << "Func C\n"; } };
class D : public B, public C { public: void funcD() { std::cout << "Func
D\n"; } };
int main() {
D obj;
[Link](); // Ambiguous without virtual inheritance in B and C
[Link]();
[Link]();
[Link]();
return 0;
}
In this conceptual example, D inherits from both B and C, which in turn inherit from A. This
creates a hybrid structure. Without virtual inheritance for A in B and C, calling [Link]()
would be ambiguous.
To make this a proper working example resolving ambiguity:
C++
#include <iostream>
class A { public: virtual void funcA() { std::cout << "Func A from A\n"; } };
class B : virtual public A { public: void funcB() { std::cout << "Func B\n";
} void funcA() override { std::cout << "Func A from B\n"; } };
class C : virtual public A { public: void funcC() { std::cout << "Func C\n";
} void funcA() override { std::cout << "Func A from C\n"; } };
class D : public B, public C { public: void funcD() { std::cout << "Func
D\n"; } void funcA() override { std::cout << "Func A from D\n"; } };
int main() {
D obj;
[Link](); // Now calls D's funcA due to virtual inheritance and
overriding
[Link]();
[Link]();
[Link]();
return 0;
}
Output:
Func A from D
Func B
Func C
Func D
6. Cyclic Inheritance
Definition: Cyclic inheritance occurs when a class directly or indirectly inherits from
itself. This creates a circular dependency in the inheritance hierarchy.
Not Allowed (Generally): Most programming languages, including C++, do not allow
direct cyclic inheritance because it leads to infinite recursion in class definitions and
object creation, making the size and structure of the objects undefined and causing
compilation errors.
Example (C++ - Will Result in a Compiler Error):
C++
// Direct Cyclic Inheritance (Compiler Error)
// class A : public A {};
// Indirect Cyclic Inheritance (Compiler Error)
class B : public C {};
class C : public B {};
int main() {
// B objB; // Will not compile
// C objC; // Will not compile
return 0;
}
The C++ compiler will detect such cyclic dependencies and issue an error, preventing the
program from compiling. Inheritance should always form a directed acyclic graph (DAG) to
maintain a well-defined class hierarchy.
PREPARED BY : Syed Muhammad Aoun Abbas Zaidi
ADP IT 2ND BLUE