Inheritance In C++
Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a class (derived class) to inherit properties and behaviors from another class (base class). In C++, inheritance can be categorized into three types based on the access level of the inherited members: public, private, and protected inheritance.
Access Modifiers
In C++, access modifiers are keywords used to specify the accessibility of class members (variables and functions) from outside the class. There are three access modifiers in C++: public, private, and protected.
-
Public Access Modifier - When a class member is declared as public, it can be accessed from outside the class through objects of that class. Public members are accessible from anywhere in the program, including outside the class and its derived classes.
-
Private Access Modifier - When a class member is declared as private, it can only be accessed by other members of the same class.
-
Protected Access Modifier - When a class member is declared as protected, it can be accessed by other members of the same class and its derived classes.
Example Code:
Output:
In this example:
- The publicMember and publicFunction() are accessible from outside the class.
- The privateMember and privateFunction() are private members and are not accessible from outside the class.
- The protectedMember and protectedFunction() are protected members and are not accessible from outside the class but can be accessed by derived classes.
Derived Class Declaration
A derived class is declared by specifying the base class from which it inherits using a colon :
followed by the access specifier (public, private, or protected) and the base class name.
Here's the general syntax:
Public Inheritance
In public inheritance, all public members of the base class become public members of the derived class, and all protected members of the base class become protected members of the derived class. However, the private members of the base class remain inaccessible in the derived class.
Private Inheritance
In private inheritance, all public and protected members of the base class become private members of the derived class. This means that they are not accessible outside the derived class.
Protected Inheritance
In protected inheritance, all public and protected members of the base class become protected members of the derived class. This means that they are accessible within the derived class and its derived classes but not outside of them.
Example Code:
Here's an example demonstrating inheritance in C++:
Output:
Explanation:
-
For DerivedPublic class (public inheritance):
- DerivedPublic class inherits publicly from Base class. Therefore, both x and y of the Base class are accessible in the DerivedPublic class.
- The DerivedPublic class constructor is invoked when an object of DerivedPublic class is created.
- The display() function of DerivedPublic class prints the values of x and y.
-
For DerivedPrivate class (private inheritance):
- DerivedPrivate class inherits privately from Base class. This means that all members of Base class become private members of DerivedPrivate class, making them inaccessible outside DerivedPrivate class.
- The DerivedPrivate class constructor is invoked when an object of DerivedPrivate class is created.
- Attempting to call the display() function results in an error because it's inaccessible outside DerivedPrivate.
-
For DerivedProtected class (protected inheritance):
- DerivedProtected class inherits protectedly from Base class, making x and y protected members of DerivedProtected class.
- The DerivedProtected class constructor is invoked when an object of DerivedProtected class is created.
- Similar to DerivedPrivate class, the display() function is inaccessible outside DerivedProtected class.
Friend Function
In C++, a friend function is a function that is not a member of a class but has access to the class's private and protected members. When a function is declared as a friend of a class, it can access private and protected members of that class as if it were a member function of that class. This provides flexibility in defining functions that need access to private or protected members without being members of the class itself.
A friend function of a base class does not have direct access to members of a derived class, even if those members are accessible to the base class. To access members of a derived class, the friend function needs to be declared as a friend in the derived class as well.
Base Class With Friend Function:
Output:
Explanation:
- In this code, we have the Base class with private and protected members.
- We define a friend function baseFriendFunction that takes a const Base& reference as a parameter to access private and protected members of the Base class.
- Inside the main() function, we create an object baseObj of the Base class.
- We then call the baseFriendFunction with baseObj as an argument.
- The baseFriendFunction function accesses the private and protected members of baseObj, printing their values.
Derived Class with Friend Function:
Output:
Explanation:
- In this code, we have two classes: Base and Derived, where Derived publicly inherits from Base.
- We define a friend function derivedFriendFunction to access private and protected members of the Derived class.
- Inside the main() function, we create an object derivedObj of the Derived class.
- We then call the derivedFriendFunction with derivedObj as an argument.
- The derivedFriendFunction function accesses the private and protected members of the Derived class, printing their values.
Friend Classes
Friend classes in C++ provide a way to grant access to the private and protected members of one class to another class. When a class is declared as a friend of another class, it can access private and protected members of that class, just like the members of the class itself. This feature is often used when two or more classes need to share data or functionality that is not intended to be publicly accessible.
Here's a brief overview of friend classes:
- Access to Private and Protected Members: A friend class has access to all the private and protected members of the class it is declared as a friend of.
- Declaration Syntax: To declare a friend class, use the
friend
keyword followed by the class declaration inside the class that is granting friendship. - Bidirectional Friendship: Friendship is not symmetric. If class A is a friend of class B, it doesn't imply that class B is automatically a friend of class A. Friendship must be explicitly declared in both directions if needed.
Output:
In this example:
- class B is declared as a friend of class A using the friend keyword.
- class B can now access the private member privateDataA of class A.
- The accessPrivateDataA method in class B accesses the private data of class A through an object of class A.
Forms Of Inheritance
Inheritance allows a class to inherit properties and behaviors (methods) from another class. There are different forms of inheritance in C++:
Single Inheritance
![Single Inheritance](https://res.cloudinary.com/hptuexamhelper/image/upload/f_auto,q_auto/si_cs1zg9.png)
A derived class inherits from only one base class.
Output:
Explanation:
- In this code, Derived class inherits publicly from Base.
- The output displays the function calls to both the base class function display() and the derived class function show().
Multiple Inheritance
![Multiple Inheritance](https://res.cloudinary.com/hptuexamhelper/image/upload/f_auto,q_auto/mi_zitumt.png)
A derived class inherits from more than one base class.
Output:
Explanation:
- In this code, Derived class inherits from both Base1 and Base2.
- The output displays the function calls to each base class function display1() and display2() and the derived class function show().
Multilevel Inheritance
![Multilevel Inheritance](https://res.cloudinary.com/hptuexamhelper/image/upload/f_auto,q_auto/ml_ivqnse.png)
A derived class inherits from another derived class, creating a hierarchy of classes.
Output:
Explanation:
- In this code, AnotherDerived class inherits from Derived, which in turn inherits from Base.
- The output displays the function calls to each class function display(), show(), and print(), demonstrating the multilevel inheritance hierarchy.
Hierarchical Inheritance
![Hierarchical Inheritance](https://res.cloudinary.com/hptuexamhelper/image/upload/f_auto,q_auto/hierar_mrfuii.png)
Multiple derived classes inherit from a single base class.
Output:
Explanation:
- In this code, both Derived1 and Derived2 classes inherit from Base.
- The output displays the function calls to each class function display(), show1(), and show2(), demonstrating the hierarchical inheritance where multiple derived classes inherit from a single base class.
Hybrid Inheritance
![Hybrid Inheritance](https://res.cloudinary.com/hptuexamhelper/image/upload/f_auto,q_auto/hybrid_bl2ksc.png)
A combination of two or more types of inheritance.
Output:
Explanation:
- In this code, Derived3 class inherits from both Derived1 and Derived2, which in turn inherit from Base.
- The output displays the function calls to each class function display(), show1(), show2(), and print(), demonstrating hybrid inheritance where multiple inheritance forms are combined.
Virtual Base Class
Multiple inheritance occurs when a class inherits from more than one base class. The diamond problem specifically arises in situations where a class inherits from two or more classes that have a common ancestor. This can lead to ambiguity in the inheritance hierarchy because the derived class indirectly inherits from the common ancestor through multiple paths. This ambiguity can cause issues during compilation or lead to unexpected behavior in the program.
Output:
In this code:
- We have a base class Base with a simple method display.
- Two classes Derived1 and Derived2 inherit from Base.
- Another class MultipleDerived inherits from both Derived1 and Derived2.
- The MultipleDerived class now has two instances of the Base class due to the multiple inheritance paths.
- When we try to call display directly on an object of MultipleDerived, it results in a compilation error due to ambiguity. Both Derived1 and Derived2 provide their own version of Base, leading to confusion.
To resolve this ambiguity, we can use virtual inheritance.
Virtual base classes provide a solution to the diamond problem by ensuring that there's only one instance of the common ancestor class shared among the derived classes. When a class is inherited virtually, it means that the derived classes share a single instance of the virtual base class, rather than each having their own separate instance. This sharing of the base class instance prevents ambiguity and ensures that each derived class has access to a single, consistent instance of the shared base class.
Ouput:
In this code:
- Derived1 and Derived2 both inherit virtually from Base.
- MultipleDerived inherits from both Derived1 and Derived2.
- Due to virtual inheritance, there's only one shared instance of Base among all classes in the inheritance hierarchy.
- Now, calling display() on an object of MultipleDerived will correctly call the display() method from the shared Base class, avoiding ambiguity.
Abstract Class
An abstract class in C++ is a class that cannot be instantiated on its own. It serves as a blueprint for other classes and typically contains one or more pure virtual functions. A pure virtual function is a function declared in the base class that has no implementation and must be overridden by derived classes.
Output:
Explanation:
- The code defines an abstract base class Shape with a pure virtual function draw().
- The draw() function in the Shape class has no implementation (pure virtual function), indicating that any derived class must override it.
- Two concrete derived classes Rectangle and Circle inherit from the Shape class.
- Both Rectangle and Circle classes override the draw() function according to their respective shapes.
- In the main() function, objects of Rectangle and Circle are created.
- When draw() is called on the rec object (of type Rectangle), it invokes the draw() function specific to rectangles, printing "Drawing rectangle...".
- Similarly, when draw() is called on the cir object (of type Circle), it invokes the draw() function specific to circles, printing "Drawing circle...".
Advantage and disadvantage of Inheritance
Advantages
- Code Reusability: Inheritance allows classes to inherit attributes and methods from other classes, promoting code reusability and reducing redundancy.
- Extensibility: It enables the creation of new classes that are built upon existing classes, allowing for easy extension and modification of functionality without modifying the existing code.
- Polymorphism: Inheritance facilitates polymorphic behavior, where objects of derived classes can be treated as objects of their base class, leading to flexibility in programming and improved code organization.
- Modularity: It promotes a modular approach to software design by breaking down complex systems into smaller, manageable components, making the codebase easier to understand and maintain.
Disadvantages
- Complexity: Inheritance hierarchies can become complex and difficult to understand, especially in large projects, leading to maintenance challenges and potential bugs.
- Tight Coupling: Excessive use of inheritance can lead to tight coupling between classes, making the codebase less flexible and more difficult to refactor.
- Inheritance Pollution: Subclasses inherit all members (both data and methods) of their base class, which can lead to inheritance pollution and potential conflicts if not managed properly.
- Inflexibility: Changes to the base class can have unintended consequences on derived classes, potentially requiring modifications to multiple parts of the codebase, which can be time-consuming and error-prone.
Last updated on -