Single Inheritance in C++
To inherit traits from one's ancestors is what the word "inheritance" literally means. Similar to this, the idea of inheritance in programming refers to a class's subclasses inheriting that class's properties. The parent class whose attributes have been inherited is called the base class, and all classes that inherit from it are known as derived classes. This is one of the main elements of object-oriented programming. Because inheritance offers benefits like data hiding and code reusability, it improves program efficiency.
Using an example from real life, learn about the idea of inheritance. Imagine that there are three classes: apples, bananas, and grapes. The functions sellers(), customers(), and price() are shared by all three of them.
Instead of creating three distinct classes with the same functions, you can create a single class called Fruits that can inherit these common functions. This is explained in the diagrammatic illustration that follows:
Apples Bananas Grapes
sellers() | sellers() | sellers() |
customers() | customers() | customers() |
price() | price() | price() |
Without using inheritance
Program redundancy would result from distinct classes with shared functions if inheritance wasn't used.
Code reusability can be used to improve program efficiency and make the code cleaner after utilizing the inheritance concept. The schematic example above shows how to combine three redundant classes with common features to create a single class whose members can be inherited by the other derived classes.
Single inheritance
The inheritance process in which one base class gives rise to one derived class is known as single inheritance. Because it excludes all combinations of inheritance and varying degrees of inheritance, it is the most straightforward type of inheritance. The child class may inherit every member of the base class, depending on the visibility mode (private, protected, or public) selected during inheritance. Determining the visibility mode during inheritance is, nevertheless, optional. It automatically sets the visibility mode to private if you don't define it.
Lack of Clarity in C++ Single Inheritance
When implementing Single Inheritance in C++, ambiguities may occur. Ambiguities occur when functions with the same name and return type in the base class and the derived class. Function overriding refers to the process whereby the function of the derived class is invoked by default each time an object of the derived class calls said function. To avoid this kind of unclear situation, you can define these functions independently using a scope resolution operator.
#include <iostream>
#include <string>
using namespace std;
// base class
class Organization
{
protected:
string orgName;
string orgSector;
public:
Organization() : orgName("XYZ Corp"), orgSector("Technology") {}
// showInfo() function of base class
void showInfo()
{
cout << "Organization Info:" << endl;
cout << "Name: " << orgName << endl;
cout << "Sector: " << orgSector << endl;
}
};
// derived class
class Employee : public Organization
{
private:
int empID;
public:
Employee() : empID(4004)
{
orgName = "Employee_D";
}
// showInfo() function of derived class
void showInfo()
{
cout << "Employee Info:" << endl;
cout << "Name: " << orgName << endl;
cout << "ID: " << empID << endl;
}
};
int main()
{
//make an object from the derived class
Employee obj;
// use the showInfo() function
obj.showInfo();
cout << "\n";
// call the derived class object's showInfo() function
obj.Employee::showInfo();
return 0;
}
Output
The aforementioned program uses the scope resolution operator to call the showInfo() function of the base class and the derived class with the same name and return type.
obj.showInfo();
When the object of the derived class calls the showInfo() function, the showInfo() of the derived class will be called, superseding the showInfo() of the base class.
obj.organization::showInfo();
Now, it is stated clearly that the object calls the base class's showName() function. Consequently, showName() from the base class is called without being overridden.
Inheritance-Based Visibility Modes
Within the derived classes, the visibility mode indicates which members are inherited and under what control. In single inheritance, there are three visibility modes in which a class can inherit a base class:
1. Mode of Public Visibility
You can access every member of the base class in the public visibility mode by simply using their access specifiers. In the derived class, the members that are identified as private, protected, and public in the base class likewise stay that way, in that sequence. This implies that all other classes, including the derived class, can also access the public members. The derived class and its members will be the only ones with access to the protected members; the private members will remain inaccessible to them.
Here is a sample of code that shows how to make use of the public visibility mode in a derived class using single inheritance:
class parent_class
{
// members of the data
// functions of the member
};
class child_class: public parent_class
{
// members of the data
// functions of the member
};
Using each of the base class's three access specifiers, the public visibility mode is demonstrated by the code that follows:
#include <iostream>
using namespace std;
class Base {
public:
int publicVar;
protected:
int protectedVar;
private:
int privateVar;
};
// Visibility mode of Derived is public
// So access specifiers will remain the same
class Derived : public Base {
};
// Main function
int main() {
Derived myObject;
// Accessible
cout << "Value of publicVar is " << myObject.publicVar << endl;
// Accessible (due to protected inheritance)
cout << "Value of protectedVar is " << myObject.protectedVar << endl;
// Not accessible (private member)
cout << "Value of privateVar is " << myObject.privateVar << endl;
return 0;
}
Output
Since the derived class derived_class in the example above has its visibility set to public, all of the access specifiers will stay the same. Since publicVar is a public member, it can be accessed from outside the derived class. Since protectedVar is a protected member, the provided code cannot access it; it can only be accessed within the derived class. privateVar, on the other hand, is not available outside of the base class base_class because it is a private member.
2. Mode of Private Visibility
The visibility mode can be changed to private, which makes all of the access specifiers—private, protected, and public. This means that they can only be accessed within the class that defines them. The only way to access them is via the member functions that belong to the same class. Furthermore, these members cannot be further inherited because it is unable to inherit the private members.
How to use the private visibility mode in a derived class with single inheritance is demonstrated by the following code snippet:
class parent_class
{
// members of the data
// functions of the member
};
class child_class: private parent_class
{
//members of the data
// functions of the member
};
The code that follows demonstrates how the base class's three access specifiers—private visibility mode and work together:
#include <iostream>
using namespace std;
class ParentClass {
public:
int publicVar;
protected:
int protectedVar;
private:
int privateVar;
};
// Since ChildClass's visibility mode is private
//all access specifiers will also become private
class ChildClass : private ParentClass {
};
// Main function
int main() {
ChildClass obj;
// Not accessible (private member in parent class)
cout << "Value of publicVar is " << obj.publicVar << endl;
// Not accessible (private member in parent class)
cout << "Value of protectedVar is " << obj.protectedVar << endl;
// Not accessible (private member in parent class)
cout << "Value of privateVar is " << obj.privateVar << endl;
return 0;
}
Output
The derived class ChildClass in the example above has private visibility mode. Thus, in the derived class, every member of the base class is made private. A derived class object raises an error when it tries to obtain these elements outside of the class.
3. Mode of Protected Visibility
The base class's private members stay private while the public and private members are protected in the protected visibility mode. As a result, only the derived class has access to the general public and protected base class members. Should you attempt to access them from outside the derived class, an error will be raised. The private member won't be available until after the base class ends.
A derived class with single inheritance can use the protected visibility mode as demonstrated in the following code snippet:
class parent_class
{
// members of the data
// functions of the member
};
class child_class: protected parent_class
{
//members of the data
// functions of the member
};
Using each of the base class's three access specifiers, the public visibility mode is demonstrated by the code that follows:
#include <iostream>
using namespace std;
class ParentClass {
public:
int publicVar;
protected:
int protectedVar;
private:
int privateVar;
};
// Visibility mode of ChildClass is protected
// So public becomes protected
class ChildClass : protected ParentClass {
};
// Main function
int main() {
ChildClass obj;
// Not accessible (protected member in parent class)
cout << "Value of publicVar is " << obj.publicVar << endl;
// Not accessible (protected member in parent class)
cout << "Value of protectedVar is " << obj.protectedVar << endl;
// Not accessible (private member in parent class)
cout << "Value of privateVar is " << obj.privateVar << endl;
return 0;
}
Output
In this case, it safeguards the derived class child_class's visibility mode. As a result, publicVar becomes a protected member while protectedVar stays a protected member; as a result, neither of them is accessible from outside the derived class. privateVar, however, is still a private member and cannot be accessed from outside of the base class parent_class.