UNIT 2
Inheritance and Pointers
In C++, inheritance is a process in which one object acquires all the properties and behaviors of its parent object automatically. In such way, you can reuse, extend or modify the attributes and behaviors which are defined in other class.
In C++, the class which inherits the members of another class is called derived class and the class whose members are inherited is called base class. The derived class is the specialized class for the base class.
Advantage of C++ Inheritance
Code reusability: Now you can reuse the members of your parent class. So, there is no need to define the member again. So less code is required in the class.
Types Of Inheritance
C++ supports five types of inheritance:
Derived Classes
A Derived class is defined as the class derived from the base class.
The Syntax of Derived class:
Where,
derived_class_name: It is the name of the derived class.
visibility mode: The visibility mode specifies whether the features of the base class are publicly inherited or privately inherited. It can be public or private.
base_class_name: It is the name of the base class.
Note:
C++ Single Inheritance
Single inheritance is defined as the inheritance in which a derived class is inherited from the only one base class.
Where 'A' is the base class, and 'B' is the derived class.
C++ Single Level Inheritance Example: Inheriting Fields
When one class inherits another class, it is known as single level inheritance. Let's see the example of single level inheritance which inherits the fields only.
Output:
Salary: 60000
Bonus: 5000
In the above example, Employee is the base class and Programmer is the derived class.
C++ Single Level Inheritance Example: Inheriting Methods
Let's see another example of inheritance in C++ which inherits methods only.
Output:
Eating...
Barking...
Let's see a simple example.
Output:
Multiplication of a and b is : 20
In the above example, class A is privately inherited. Therefore, the mul() function of class 'A' cannot be accessed by the object of class B. It can only be accessed by the member function of class B.
How to make a Private Member Inheritable
The private member is not inheritable. If we modify the visibility mode by making it public, but this takes away the advantage of data hiding.
C++ introduces a third visibility modifier, i.e., protected. The member which is declared as protected will be accessible to all the member functions within the class as well as the class immediately derived from it.
Visibility modes can be classified into three categories:
Visibility of Inherited Members
Base class visibility | Derived class visibility | ||
Public | Private | Protected | |
Private | Not Inherited | Not Inherited | Not Inherited |
Protected | Protected | Private | Protected |
Public | Public | Private | Protected |
C++ Multilevel Inheritance
Multilevel inheritance is a process of deriving a class from another derived class.
C++ Multi Level Inheritance Example
When one class inherits another class which is further inherited by another class, it is known as multi level inheritance in C++. Inheritance is transitive so the last derived class acquires all the members of all its base classes.
Let's see the example of multi level inheritance in C++.
Output:
Eating...
Barking...
Weeping...
C++ Multiple Inheritance
Multiple inheritance is the process of deriving a new class that inherits the attributes from two or more classes.
Syntax of the Derived class:
Let's see a simple example of multiple inheritance.
Output:
The value of a is : 10
The value of b is : 20
Addition of a and b is : 30
In the above example, class 'C' inherits two base classes 'A' and 'B' in a public mode.
Ambiquity Resolution in Inheritance
Ambiguity can be occurred in using the multiple inheritance when a function with the same name occurs in more than one base class.
Let's understand this through an example:
Output:
error: reference to 'display' is ambiguous
display();
An ambiguity can also occur in single inheritance.
Consider the following situation:
In the above case, the function of the derived class overrides the method of the base class. Therefore, call to the display() function will simply call the function defined in the derived class. If we want to invoke the base class function, we can use the class resolution operator.
C++ Hybrid Inheritance
Hybrid inheritance is a combination of more than one type of inheritance.
Let's see a simple example:
Output:
Enter the value of 'a' :
10
Enter the value of 'b' :
20
Enter the value of c is :
30
Multiplication of a,b,c is : 6000
C++ Hierarchical Inheritance
Hierarchical inheritance is defined as the process of deriving more than one class from a base class.
Syntax of Hierarchical inheritance:
Let's see a simple example:
Output:
Enter the length and breadth of a rectangle:
23
20
Area of the rectangle is : 460
Enter the base and height of the triangle:
2
5
Area of the triangle is : 5
Data hiding is one of the important features of Object Oriented Programming which allows preventing the functions of a program to access directly the internal representation of a class type. The access restriction to the class members is specified by the labeled public, private, and protected sections within the class body. The keywords public, private, and protected are called access specifiers.
A class can have multiple public, protected, or private labeled sections. Each section remains in effect until either another section label or the closing right brace of the class body is seen. The default access for members and classes is private.
class Base {
public:
// public members go here
protected:
// protected members go here
private:
// private members go here
};
The public Members
A public member is accessible from anywhere outside the class but within a program. You can set and get the value of public variables without any member function as shown in the following example −
#include <iostream>
using namespace std;
class Line {
public:
double length;
void setLength( double len );
double getLength( void );
};
// Member functions definitions
double Line::getLength(void) {
return length ;
}
void Line::setLength( double len) {
length = len;
}
// Main function for the program
int main() {
Line line;
// set line length
line.setLength(6.0);
cout << "Length of line : " << line.getLength() <<endl;
// set line length without member function
line.length = 10.0; // OK: because length is public
cout << "Length of line : " << line.length <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Length of line : 6
Length of line : 10
The private Members
A private member variable or function cannot be accessed, or even viewed from outside the class. Only the class and friend functions can access private members.
By default all the members of a class would be private, for example in the following class width is a private member, which means until you label a member, it will be assumed a private member −
class Box {
double width;
public:
double length;
void setWidth( double wid );
double getWidth( void );
};
Practically, we define data in private section and related functions in public section so that they can be called from outside of the class as shown in the following program.
#include <iostream>
using namespace std;
class Box {
public:
double length;
void setWidth( double wid );
double getWidth( void );
private:
double width;
};
// Member functions definitions
double Box::getWidth(void) {
return width ;
}
void Box::setWidth( double wid ) {
width = wid;
}
// Main function for the program
int main() {
Box box;
// set box length without member function
box.length = 10.0; // OK: because length is public
cout << "Length of box : " << box.length <<endl;
// set box width without member function
// box.width = 10.0; // Error: because width is private
box.setWidth(10.0); // Use member function to set it.
cout << "Width of box : " << box.getWidth() <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Length of box : 10
Width of box : 10
The protected Members
A protected member variable or function is very similar to a private member but it provided one additional benefit that they can be accessed in child classes which are called derived classes.
You will learn derived classes and inheritance in next chapter. For now you can check following example where I have derived one child class SmallBox from a parent class Box.
Following example is similar to above example and here width member will be accessible by any member function of its derived class SmallBox.
#include <iostream>
using namespace std;
class Box {
protected:
double width;
};
class SmallBox:Box { // SmallBox is the derived class.
public:
void setSmallWidth( double wid );
double getSmallWidth( void );
};
// Member functions of child class
double SmallBox::getSmallWidth(void) {
return width ;
}
void SmallBox::setSmallWidth( double wid ) {
width = wid;
}
// Main function for the program
int main() {
SmallBox box;
// set box width using member function
box.setSmallWidth(5.0);
cout << "Width of box : "<< box.getSmallWidth() << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Width of box : 5
One of the most important concepts in object-oriented programming is that of inheritance. Inheritance allows us to define a class in terms of another class, which makes it easier to create and maintain an application. This also provides an opportunity to reuse the code functionality and fast implementation time.
When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class, and the new class is referred to as the derived class.
The idea of inheritance implements the is a relationship. For example, mammal IS-A animal, dog IS-A mammal hence dog IS-A animal as well and so on.
Base and Derived Classes
A class can be derived from more than one classes, which means it can inherit data and functions from multiple base classes. To define a derived class, we use a class derivation list to specify the base class(es). A class derivation list names one or more base classes and has the form −
class derived-class: access-specifier base-class
Where access-specifier is one of public, protected, or private, and base-class is the name of a previously defined class. If the access-specifier is not used, then it is private by default.
Consider a base class Shape and its derived class Rectangle as follows −
#include <iostream>
using namespace std;
// Base class
class Shape {
public:
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
protected:
int width;
int height;
};
// Derived class
class Rectangle: public Shape {
public:
int getArea() {
return (width * height);
}
};
int main(void) {
Rectangle Rect;
Rect.setWidth(5);
Rect.setHeight(7);
// Print the area of the object.
cout << "Total area: " << Rect.getArea() << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Total area: 35
Access Control and Inheritance
A derived class can access all the non-private members of its base class. Thus base-class members that should not be accessible to the member functions of derived classes should be declared private in the base class.
We can summarize the different access types according to - who can access them in the following way −
Access | public | protected | private |
Same class | yes | yes | yes |
Derived classes | yes | yes | no |
Outside classes | yes | no | no |
A derived class inherits all base class methods with the following exceptions −
Type of Inheritance
When deriving a class from a base class, the base class may be inherited through public, protected or private inheritance. The type of inheritance is specified by the access-specifier as explained above.
We hardly use protected or private inheritance, but public inheritance is commonly used. While using different type of inheritance, following rules are applied −
Multiple Inheritance
A C++ class can inherit members from more than one class and here is the extended syntax −
class derived-class: access baseA, access baseB....
Where access is one of public, protected, or private and would be given for every base class and they will be separated by comma as shown above. Let us try the following example −
#include <iostream>
using namespace std;
// Base class Shape
class Shape {
public:
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
protected:
int width;
int height;
};
// Base class PaintCost
class PaintCost {
public:
int getCost(int area) {
return area * 70;
}
};
// Derived class
class Rectangle: public Shape, public PaintCost {
public:
int getArea() {
return (width * height);
}
};
int main(void) {
Rectangle Rect;
int area;
Rect.setWidth(5);
Rect.setHeight(7);
area = Rect.getArea();
// Print the area of the object.
cout << "Total area: " << Rect.getArea() << endl;
// Print the total cost of painting
cout << "Total paint cost: $" << Rect.getCost(area) << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Total area: 35
Total paint cost: $2450
The Class Constructor
A class constructor is a special member function of a class that is executed whenever we create new objects of that class.
A constructor will have exact same name as the class and it does not have any return type at all, not even void. Constructors can be very useful for setting initial values for certain member variables.
Following example explains the concept of constructor −
#include <iostream>
using namespace std;
class Line {
public:
void setLength( double len );
double getLength( void );
Line(); // This is the constructor
private:
double length;
};
// Member functions definitions including constructor
Line::Line(void) {
cout << "Object is being created" << endl;
}
void Line::setLength( double len ) {
length = len;
}
double Line::getLength( void ) {
return length;
}
// Main function for the program
int main() {
Line line;
// set line length
line.setLength(6.0);
cout << "Length of line : " << line.getLength() <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Object is being created
Length of line : 6
Parameterized Constructor
A default constructor does not have any parameter, but if you need, a constructor can have parameters. This helps you to assign initial value to an object at the time of its creation as shown in the following example −
#include <iostream>
using namespace std;
class Line {
public:
void setLength( double len );
double getLength( void );
Line(double len); // This is the constructor
private:
double length;
};
// Member functions definitions including constructor
Line::Line( double len) {
cout << "Object is being created, length = " << len << endl;
length = len;
}
void Line::setLength( double len ) {
length = len;
}
double Line::getLength( void ) {
return length;
}
// Main function for the program
int main() {
Line line(10.0);
// get initially set length.
cout << "Length of line : " << line.getLength() <<endl;
// set line length again
line.setLength(6.0);
cout << "Length of line : " << line.getLength() <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Object is being created, length = 10
Length of line : 10
Length of line : 6
Using Initialization Lists to Initialize Fields
In case of parameterized constructor, you can use following syntax to initialize the fields −
Line::Line( double len): length(len) {
cout << "Object is being created, length = " << len << endl;
}
Above syntax is equal to the following syntax −
Line::Line( double len) {
cout << "Object is being created, length = " << len << endl;
length = len;
}
If for a class C, you have multiple fields X, Y, Z, etc., to be initialized, then use can use same syntax and separate the fields by comma as follows −
C::C( double a, double b, double c): X(a), Y(b), Z(c) {
....
}
The Class Destructor
A destructor is a special member function of a class that is executed whenever an object of it's class goes out of scope or whenever the delete expression is applied to a pointer to the object of that class.
A destructor will have exact same name as the class prefixed with a tilde (~) and it can neither return a value nor can it take any parameters. Destructor can be very useful for releasing resources before coming out of the program like closing files, releasing memories etc.
Following example explains the concept of destructor −
#include <iostream>
using namespace std;
class Line {
public:
void setLength( double len );
double getLength( void );
Line(); // This is the constructor declaration
~Line(); // This is the destructor: declaration
private:
double length;
};
// Member functions definitions including constructor
Line::Line(void) {
cout << "Object is being created" << endl;
}
Line::~Line(void) {
cout << "Object is being deleted" << endl;
}
void Line::setLength( double len ) {
length = len;
}
double Line::getLength( void ) {
return length;
}
// Main function for the program
int main() {
Line line;
// set line length
line.setLength(6.0);
cout << "Length of line : " << line.getLength() <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Object is being created
Length of line : 6
Object is being deleted
If base class and derived class have member functions with same prototypes, such functions are called as overrided functions. They are used only in inheritance.
Example
class Base
{
public:
void Data()
{
cout<<”Base class”;
}
};
class Derived: public Base
{
public:
void Data() // overrided function
{
cout<<”Derived class”;
}
};
Object of base class is used to access base class version of member function and derived class object is used to access derived class version of member function. This is shown in program given below.
class Base { public: void Data() { cout<<”Base class”; } }; class Derived: public Base { public: void Data() { cout<<”Derived class”; } }; int main() { Base b; Derived d; b.Data(); d.Data (); return 0; } | //Defines Base class
//Defines function Data of Base class
//Defines “Derived” class that is sub class of “Base”.
//Defines function Data of “Derived” class
//Defines main
//Creates base class object //Creates derived class object
//Calls Data function of base class //Calls Data function of derived class |
So output of above program will be :
Output
Base class
Derived class
When several classes are derived from common base class it is called hierarchical inheritance.
In C++ hierarchical inheritance, the feature of the base class is inherited onto more than one sub-class.
For example, a car is a common class from which Audi, Ferrari, Maruti etc can be derived.
Following block diagram highlights its concept.
C++ Hierarchical Inheritance Block Diagram
As shown in above block diagram, in C++ hierarchical inheritance all the derived classes have common base class. The base class includes all the features that are common to derived classes.
As in other inheritance, based on the visibility mode used or access specifier used while deriving, the properties of the base class are derived. Access specifier can be private, protected or public.
C++ Hierarchical Inheritance Syntax
class A // base class
{
..............
};
class B : access_specifier A // derived class from A
{
...........
} ;
class C : access_specifier A // derived class from A
{
...........
} ;
class D : access_specifier A // derived class from A
{
...........
} ;
C++ Hierarchical Inheritance Example
// hierarchial inheritance.cpp
#include <iostream>
using namespace std;
class A //single base class
{
public:
int x, y;
void getdata()
{
cout << "\nEnter value of x and y:\n"; cin >> x >> y;
}
};
class B : public A //B is derived from class base
{
public:
void product()
{
cout << "\nProduct= " << x * y;
}
};
class C : public A //C is also derived from class base
{
public:
void sum()
{
cout << "\nSum= " << x + y;
}
};
int main()
{
B obj1; //object of derived class B
C obj2; //object of derived class C
obj1.getdata();
obj1.product();
obj2.getdata();
obj2.sum();
return 0;
} //end of program
Output
Enter value of x and y:
2
3
Product= 6
Enter value of x and y:
2
3
Sum= 5
Explanation
In this example, there is only one base class A from which two class B and C are derived.
Both derived class have their own members as well as base class members.
The product is calculated in the derived class B, whereas, the sum is calculated in the derived class C but both use the values of x and y from the base class.
In C++ inheritance we can derive a child class from the base class in different access modes. For example,
class Base {
.... ... ....
};
class Derived : public Base {
.... ... ....
};
Notice the keyword public in the code
class Derived : public Base
This means that we have created a derived class from the base class in public mode. Alternatively, we can also derive classes in protected or private modes.
These 3 keywords (public, protected, and private) are known as access specifiers in C++ inheritance.
public, protected and private inheritance in C++
public, protected, and private inheritance have the following features:
Note: private members of the base class are inaccessible to the derived class.
class Base {
public:
int x;
protected:
int y;
private:
int z;
};
class PublicDerived: public Base {
// x is public
// y is protected
// z is not accessible from PublicDerived
};
class ProtectedDerived: protected Base {
// x is protected
// y is protected
// z is not accessible from ProtectedDerived
};
class PrivateDerived: private Base {
// x is private
// y is private
// z is not accessible from PrivateDerived
}
Example 1: C++ public Inheritance
// C++ program to demonstrate the working of public inheritance
#include <iostream>
using namespace std;
class Base {
private:
int pvt = 1;
protected:
int prot = 2;
public:
int pub = 3;
// function to access private member
int getPVT() {
return pvt;
}
};
class PublicDerived : public Base {
public:
// function to access protected member from Base
int getProt() {
return prot;
}
};
int main() {
PublicDerived object1;
cout << "Private = " << object1.getPVT() << endl;
cout << "Protected = " << object1.getProt() << endl;
cout << "Public = " << object1.pub << endl;
return 0;
}
Output
Private = 1
Protected = 2
Public = 3
Here, we have derived PublicDerived from Base in public mode.
As a result, in PublicDerived:
Since private and protected members are not accessible, we need to create public functions getPVT() and getProt() to access them:
// Error: member "Base::pvt" is inaccessible
cout << "Private = " << object1.pvt;
// Error: member "Base::prot" is inaccessible
cout << "Protected = " << object1.prot;
Accessibility in Public Inheritance
Accessibility | private members | protected members | public members |
Base Class | Yes | Yes | Yes |
Derived Class | No | Yes | Yes |
Example 2: C++ protected Inheritance
// C++ program to demonstrate the working of protected inheritance
#include <iostream>
using namespace std;
class Base {
private:
int pvt = 1;
protected:
int prot = 2;
public:
int pub = 3;
// function to access private member
int getPVT() {
return pvt;
}
};
class ProtectedDerived : protected Base {
public:
// function to access protected member from Base
int getProt() {
return prot;
}
// function to access public member from Base
int getPub() {
return pub;
}
};
int main() {
ProtectedDerived object1;
cout << "Private cannot be accessed." << endl;
cout << "Protected = " << object1.getProt() << endl;
cout << "Public = " << object1.getPub() << endl;
return 0;
}
Output
Private cannot be accessed.
Protected = 2
Public = 3
Here, we have derived ProtectedDerived from Base in protected mode.
As a result, in ProtectedDerived:
As we know, protected members cannot be accessed directly.
As a result, we cannot use getPVT() from ProtectedDerived. That is also why we need to create the getPub() function in ProtectedDerived in order to access the pub variable.
// Error: member "Base::getPVT()" is inaccessible
cout << "Private = " << object1.getPVT();
// Error: member "Base::pub" is inaccessible
cout << "Public = " << object1.pub;
Accessibility in Protected Inheritance
Accessibility | private members | protected members | public members |
Base Class | Yes | Yes | Yes |
Derived Class | No | Yes | Yes (inherited as protected variables) |
Example 3: C++ private Inheritance
// C++ program to demonstrate the working of private inheritance
#include <iostream>
using namespace std;
class Base {
private:
int pvt = 1;
protected:
int prot = 2;
public:
int pub = 3;
// function to access private member
int getPVT() {
return pvt;
}
};
class PrivateDerived : private Base {
public:
// function to access protected member from Base
int getProt() {
return prot;
}
// function to access private member
int getPub() {
return pub;
}
};
int main() {
PrivateDerived object1;
cout << "Private cannot be accessed." << endl;
cout << "Protected = " << object1.getProt() << endl;
cout << "Public = " << object1.getPub() << endl;
return 0;
}
Output
Private cannot be accessed.
Protected = 2
Public = 3
Here, we have derived PrivateDerived from Base in private mode.
As a result, in PrivateDerived:
As we know, private members cannot be accessed directly.
As a result, we cannot use getPVT() from PrivateDerived. That is also why we need to create the getPub() function in PrivateDerived in order to access the pub variable.
// Error: member "Base::getPVT()" is inaccessible
cout << "Private = " << object1.getPVT();
// Error: member "Base::pub" is inaccessible
cout << "Public = " << object1.pub;
Accessibility in Private Inheritance
Accessibility | private members | protected members | public members |
Base Class | Yes | Yes | Yes |
Derived Class | No | Yes (inherited as private variables) | Yes (inherited as private variables) |
Single Inheritance
● It consists of single base and single derived class.
● Derived class inherits all the protected and public members from single base class.
● Private data members of base class will not be inherited.
☞ General form
class derived-class : access specifier base-class
{
//Body of derived class
};
Fig: Single Inheritance
|
class A { //Body of class A }; class B : public A { //Body of class B }; |
Program
Write a program in C++ to illustrate single inheritance.
Solution :
#include<iostream> using namespace std ; class Employee { protected: int id; char name[10]; public: void accept() { cout<<“Enter id of employee”; cin>>id; cout<<“Enter name of employee”; cin>>name; } }; class Salary: public Employee { protected: float amount, hra, da, basic; public: void getdata() { accept(); cout<<“enter basic, da and hra”; cin>>basic>>da>>hra; } void display() { amount=basic+da+hra; cout<<“NAME:”<<name<<endl; cout<<“ID:”<<id<<endl; cout<<“SALARY:”<<amount; } }; int main() { Salary S; S.getdata(); S.display(); return 0 ; } | //Declares header file
//Step 1 Declares and defines base class Employee
//Step 2 Declares id and name under protected section
//Step 3 Defines accept function under public section
//Accepting id and name of employee
//End of accept function //End of class Employee //Step 4 Create derived class Salary from base class Employee
//Step 5 Declares data members under protected section
//Step 6 Defines getdata function
//Step 7 Calls accept function //Accepting details of salary
//End of getdata function //Step 8 Defines display function
//Calculates salary
//Displaying name id and salary of employee
//End of display function //End of derived class salary //Starts main function
//Step 9 Creates object S //Step 10 Calls getdata function //Calls display function |
Explanation
Step 1 : Creates base class Employee.
As it is single inheritance only one base class is there.
class Employee //Declares and defines base class Employee
Step 2 : id and name are declared under protected section so that they are accessible to its immediate derived class .
protected:
int id; //Declares id and name under protected section
char name[10];
Step 3 : Accept function accepts details of employee.
void accept() //Defines accept function under public section
{
cout<<“Enter id of employee”;
//Accepting id and name of employee
cin>>id;
cout<<“Enter name of employee”;
cin>>name;
} //End of accept function
Step 4 : Creates derived class Salary from base class under public derivation.
All protected members remains protected and public members remain public in public derivation.
class Salary: public Employee
//Create derived class Salary from base class Employee
So data members in class Salary are as follows :
Salary | |
Protected | Public |
id name amount hra da basic |
accept() getdata() display() |
Step 5 : Declares basic, hra, da for calculation of salary.
float amount, hra, da, basic;
Step 6 : getdata accepts hra, da and basic to calculate salary.
void getdata() //Defines getdata function
Step 7 : getdata() calls accept() to get id and name.
Member function can call another member function of same class or base class directly.
getdata() calls accept() directly as it belongs to base class.
accept(); //Calls accept function
cout<<“enter basic, da and hra”;
cin>>basic>>da>>hra; //Accepting details of salary
Step 8 : Calculates salary and displays details of employee
void display() //Defines display function
{
amount=basic+da+hra; //Calculates salary
cout<<“NAME:”<<name<<endl;
//Displaying name id and salary of employee
cout<<“ID:”<<id<<endl;
cout<<“SALARY:”<<amount;
} //End of display function
Step 9 : Creates object of derived class Salary.
In inheritance object of derived class is created because derived class has access to base class but base class does not have any knowledge of its derived classes down the hierarchy.
Salary S; //Creates object S
Step 10 : Calls member functions with the help of objects and dot operator.
S.getdata(); //Calls getdata function
S.display(); //Calls display function
☞ Multiple inheritance with syntax
● It consists of multiple base classes and single derived class.
● Derived class inherits protected and public members from multiple base classes.
● If there are two base classes, then derived class inherits features from both the classes.
☞ General form
class derived-class : access specifier base-class1, access specifier base-class2
{
//Body of derived class
};
Fig: Multiple Inheritance
| class A { //Body of class A }; class B { //Body of class B }; class C : public A, public B { //Body of class C }; |
Program
Write a C++ program to illustrate multiple inheritance.
Fig.
Solution :
Fig. shows multiple inheritance where Employee, Person, Manager are classes and name, age, Department, salary, are data members of these classes.
#include<iostream> using namespace std ; class Person { protected: char Name[10]; int age; public: void accept() { cout<<“Enter name of person”; cin>>Name; cout<<“Enter age of person”; cin>> age; } }; class Employee { protected: char dept[20]; public: void getdata() { cout<<“Enter department of employee”; cin>> dept; } }; class Manager : public Person ,public Employee { protected: int salary; public: void acceptdata() { cout<<“Enter salary of employee”; cin>>salary; } void display() { cout<<“Name of Manager is”<<name; cout<<“Age of Manager is”<<age; cout<<“Department of Manager is”<<dept; cout<<“Salary of Manager is”<<salary; } }; int main() { Manager obj; obj.accept(); obj.getdata(); obj.acceptdata(); obj.display(); return 0; } |
//Step 1 Defines base class Person
//Accept details of Person
//Step 2 Defines another base class Employee
//Accept details of Employee
//Step 3 Defines sub class Manager
//Accept details of salary
//Displays details of Manager
//Defines main function
//Creates object of Manager //Access member functions of classes to display details of Manager. |
Explanation
Step 1 : Defines base class Person with data members name and age and function accept().
Data members are declared under protected section so that they are accessible to derived class.
class Person { protected: char Name[10]; int age; public: void accept() { cout<<“Enter name of person”; cin>>Name; cout<<“Enter age of person”; cin>> age; } }; | //Defines base class Person
//Accept details of Person
|
Step 2 : Defines another base class Employee.
class Employee { protected: char dept[20]; public: void getdata() { cout<<“Enter department of employee”; cin>> dept; }}; | //Defines another base class Employee
//Accept details of Employee
|
Step 3 : Defines sub class Manager that is derived from two classes Person and Employee.
● Data member is salary.
● acceptdata() function accepts salary of employee.
● display() function displays all the details of Manager.
● display() function of subclass Manager can access all the data members of super classes as they are declared under protected section and inherited under public derivation.
class Manager : public Person ,public Employee { protected: int salary; public: void acceptdata() { cout<<“Enter salary of employee”; cin>>salary; } void display() { cout<<“Name of Manager is”<<name; cout<<“Age of Manager is”<<age; cout<<“Department of Manager is”<<dept; cout<<“Salary of Manager is”<<salary; } }; | //Defines sub class Manager
//Accept details of salary
//Displays details of Manager
|
Step 4 : Creates object of derived class .This object can access all the public and protected data members and member functions of super classes.
Manager obj; | //Creates object of Manager |
Step 5 : Calls accept() function.
obj.accept(); |
Step 6 : Calls getdata() function.
obj.getdata(); |
Step 7 : Calls acceptdata() function.
obj.acceptdata(); |
Step 8 : Calls display()function.
obj.display(); |
Multilevel Inheritance
General form
class derived_class1 : access specifier base_class
{
//Body of derived class1
};
class derived_class2 : access specifier derived_class1
{
//Body of derived class2
};
.
.
.
class derived_classn : access specifier derived_class n_1
{
//Body of derived class n
};
Multilevel Inheritance
| class A { //Body of class A }; class B : public A { //Body of class B }; class C : protected B { //Body of class C }; |
Write a program to demonstrate how constructor and destructors are invoked in multilevel inheritance.
Solution :
Explanation
#include<iostream>
using namespace std ;
class base_class
{
public:
base_class()
{
cout<<“base_class constructor”<<endl;
}
~ base_class()
{
cout<<“base_class destructor”<<endl;
}
};
class derived_class1: public base
{
public:
derived_class1()
{
cout<<“derived_class1 constructor”<<endl;
}
~ derived_class1()
{
cout<<“derived_class1 destructor”<<endl;
}
};
class derived_class2: public derived_class1
{
public:
derived_class2()
{
cout<<“derived_class2 constructor”<<endl;
}
~ derived_class2()
{
cout<<“derived_class2 destructor”<<endl;
}
};
int main()
{
derived_class2 obj;
return 0 ;
}
Output
base_class constructor
derived_class1 constructor
derived_class2 constructor
derived_class2 destructor
derived_class1 destructor
base_class destructor
General form
class derived_class1 : access specifier base_class
{
//Body of derived class1
};
class derived_class2 : access specifier base_class
{
//Body of derived class2
};
.
.
.
class derived_class n : access specifier base_class
{
//Body of derived class n
};
Hierarchical Inheritance
| class A { //Body of class A }; class B : public A { //Body of class B }; class C : public A { //Body of class C }; |
Write a C++ program to illustrate hierarchical inheritance.
Fig. P. 5.4.4
Solution :
#include<iostream> using namespace std ; class Person { protected: int age; char name[10]; public: void accept() { cout<<“Enter name of person”; cin>>name; cout<<“Enter age of person”; cin>>age; } }; class Staff: public Person
{ protected: int exp; float salary; public: void getdata() { accept(); cout<<“enter experience and salary”; cin>>exp>>salary; } void display() {cout<<“NAME:”<<name<<endl; cout<<“AGE:”<<age<<endl; cout<<“Experience:”<<exp; cout<<“SALARY:”<<salary;
} }; class Student: public Person
{ protected: int marks,grade; public: void getdata1() { accept(); cout<<“enter marks and grade; cin>>marks>>grade; } void display1() { cout<<“NAME:”<<name<<endl; cout<<“AGE:”<<age<<endl; cout<<“GRADE:”<<grade; cout<<“MARKS:”<<marks; } }; int main() { Staff obj1; Student obj2; obj1.getdata(); obj1.display(); obj2.getdata1(); obj2.display1(); return 0; } | //Declares header file
//Step 1 Declares and defines base class Person
//Declares age and name under protected section
//Defines accept function under public section
//Accepting age and name of Person
//End of accept function //End of class person //Step 2 Create derived class Staff from base class Person
//Declares data members under protected section
//Defines getdata function
//Calls accept function //Accepting details of salary and experience
//End of getdata function //Defines display function
//Displaying details of Staff
//End of display function //End of derived class staff //Step 3 Create derived class Student from base class Person
//Declares data members under protected section
//Defines getdata1 function
//Calls accept function //Accepting details of marks and grade
//End of getdata function //Defines display1 function
//Displaying details of Student
//End of display1 function //End of derived class student //Starts main function
//Creates object obj1 of Staff //Step 4 Creates object obj2 of Student //Calls getdata and display function for obj1
//Calls getdata1 and display1 function for obj2
//End of main |
Explanation
Step 1 : In hierarchical inheritance there is only one base class.
#include<iostream> using namespace std ; class Person { protected: int age; char name[10]; public: void accept() { cout<<“Enter name of person”; cin>>name; cout<<“Enter age of person”; cin>>age; } }; | //Declares header file
//Declares and defines base class Person
//Declares age and name under protected section
//Defines accept function under public section
//Accepting age and name of Person
//End of accept function //End of class person |
Step 2 : In hierarchical inheritance there are multiple subclasses.
Class Staff is derived under public derivation so data members in Staff class will be
Staff | |
Protected | Public |
name age exp salary | accept() getdata() display() |
class Staff: public Person { protected: int exp; float salary; public: void getdata() {accept(); cout<<“enter experience and salary”; cin>>exp>>salary; } void display() {cout<<“NAME:”<<name<<endl; cout<<“AGE:”<<age<<endl; cout<<“Experience:”<<exp; cout<<“SALARY:”<<salary; } }; | //Create derived class Staff from base class Person
//Declares data members under protected section
//Defines getdata function //Calls accept function
//Accepting details of salary and expereince
//End of getdata function
//Defines display function //Displaying details of Staff
//End of display function //End of derived class staff |
Step 3 : Class Student is derived under public derivation so data members in student class will be
Student | |
Protected | Public |
name age marks grade | accept() getdata1() display1() |
class student { void getdata1() { accept(); cout<<“enter marks and grade”; cin>>marks>>grade; } void display1() { cout<<“NAME:”<<name<<endl; cout<<“AGE:”<<age<<endl; cout<<“GRADE:”<<grade; cout<<“MARKS:”<<marks; } }; |
//Defines getdata1 function
//Calls accept function //Accepting details of marks and grade
//End of getdata function //Defines display1 function
//Displaying details of Student
//End of display1 function //End of derived class student |
Hybrid Inheritance
Hybrid Inheritance
| class A { //Body of class A }; class B : A { //Body of class B }; class C : public A { //Body of class C }; class D : public B, protected C { //Body of class D }; |
Write a C++ program to illustrate hybrid inheritance.
Fig.
Solution :
#include <iostream> using namespace std ; class Employee–––––––––––––––– { protected: char Emp_Name[10]; char dept[20]; public: void accept() { cout<<“Enter name of employee”; cin>>Emp_Name; cout<<“Enter department of employee”; cin>> dept; } }; class Project : public Employee ––– { protected: char Pro_name[10]; int Pro_id; public: void getdata() { cout<<“Enter name of project”; cin>>Pro_name; cout<<“Enter id of project”; cin>>Pro_id; } }; class Salary ––––––––––––––––––– { protected: int amount; public: void acceptdata() { cout<<“Enter amount of salary”; cin>>amount; } }; class Emp_Info : –––––––––––––––– public Project, public Salary { public: void display() { cout<<“Name of employee is”<<Emp_Name; cout<<“Department of employee is”<<dept; cout<<“Name of Project is”<<Pro_name; cout<<“ Id of Project is”<<Pro_id; cout<<“Salary of employee is”<<amount; } }; int main() { Emp_Info obj; obj.accept(); obj.getdata(); obj.acceptdata(); obj.display(); return 0; } |
//1.Defines base class Employee
//Accept details of employee
//2.Defines sub class project
//Accept details of Project
//3.Defines class Salary
//Accept details of salary
//4. Defines sub class Emp_Info
//Displays details of employee
//Defines main function
//Creates object of Emp_Info
//Access member functions of classes to display details of employee.
|
Explanation
Step 1 : Defines base class employee with data members name and department and function accept.
Data members are declared under protected section so that they are accessible to derived class.
class Employee { protected: char Emp_Name[10]; char dept[20]; public: void accept() { cout<<“Enter name of employee”; cin>>Emp_Name; cout<<“Enter department of employee”; cin>> dept; } }; | //Defines base class Employee
//Accept details of employee
|
Step 2 :
Step 3 :
class Salary { protected: int amount; public: void acceptdata() { cout<<“Enter amount of salary”; cin>>amount; } }; | //Defines base class Employee
//Accept details of employee
|
Step 4 :
class Emp_Info : public Project, public Salary { public: void display() { cout<<“Name of employee is”<<Emp_Name; cout<<“Department of employee is”<<dept; cout<<“Name of Project is”<<Pro_name; cout<<“ Id of Project is”<<Pro_id; cout<<“Salary of employee is”<<amount; } }; | //Defines sub class Emp_Info
//Displays details of employee
|
Step 5 : Creates object of derived class that is lowest in hierarchy. This object can access all the public and protected member functions of super classes.
| Emp_Info obj; | //Creates object of Emp_Info |
Step 6 : Calls accept() function.
obj.accept(); |
Step 7 : Calls getdata() function.
obj.getdata(); |
Step 8 : Calls acceptdata() function.
obj.acceptdata(); |
Step 9 : Calls display()function.
obj.display(); |
C++ Multipath Inheritance
A derived class with two base classes and these two base classes have one common base class is called multipath inheritance.
C++ Ambiguity
Ambiguity in C++ occur when a derived class have two base classes and these two base classes have one common base class. Consider the followling figure:
Example of, occurrence of C++ ambiguity
#include<iostream.h>
#include<conio.h>
class ClassA
{
public:
int a;
};
class ClassB : public ClassA
{
public:
int b;
};
class ClassC : public ClassA
{
public:
int c;
};
class ClassD : public ClassB, public ClassC
{
public:
int d;
};
void main()
{
ClassD obj;
//obj.a = 10; //Statement 1, Error occur
//obj.a = 100; //Statement 2, Error occur
obj.ClassB::a = 10; //Statement 3
obj.ClassC::a = 100; //Statement 4
obj.b = 20;
obj.c = 30;
obj.d = 40;
cout<< "\n A from ClassB : "<< obj.ClassB::a;
cout<< "\n A from ClassC : "<< obj.ClassC::a;
cout<< "\n B : "<< obj.b;
cout<< "\n C : "<< obj.c;
cout<< "\n D : "<< obj.d;
}
Output :
A from ClassB : 10
A from ClassC : 100
B : 20
C : 30
D : 40
In the above example, both ClassB & ClassC inherit ClassA, they both have single copy of ClassA. However ClassD inherit both ClassB & ClassC, therefore ClassD have two copies of ClassA, one from ClassB and another from ClassC.
If we need to access the data member a of ClassA through the object of ClassD, we must specify the path from which a will be accessed, whether it is from ClassB or ClassC, bco'z compiler can't differentiate between two copies of ClassA in ClassD.
There are two ways to avoid c++ ambiguity.
1. Avoid ambiguity using scope resolution operator
Using scope resolution operator we can manually specify the path from which data member a will be accessed, as shown in statement 3 and 4, in the above example.
obj.ClassB::a = 10; //Statement 3
obj.ClassC::a = 100; //Statement 4
Note : still, there are two copies of ClassA in ClassD.
2. Avoid ambiguity using virtual base class
To remove multiple copies of ClassA from ClassD, we must inherit ClassA in ClassB and ClassC as virtual class.
Example to avoid ambiguity by making base class as a virtual base class
#include<iostream.h>
#include<conio.h>
class ClassA
{
public:
int a;
};
class ClassB : virtual public ClassA
{
public:
int b;
};
class ClassC : virtual public ClassA
{
public:
int c;
};
class ClassD : public ClassB, public ClassC
{
public:
int d;
};
void main()
{
ClassD obj;
obj.a = 10; //Statement 3
obj.a = 100; //Statement 4
obj.b = 20;
obj.c = 30;
obj.d = 40;
cout<< "\n A : "<< obj.a;
cout<< "\n B : "<< obj.b;
cout<< "\n C : "<< obj.c;
cout<< "\n D : "<< obj.d;
}
Output :
A : 100
B : 20
C : 30
D : 40
According to the above example, ClassD have only one copy of ClassA therefore statement 4 will overwrite the value of a, given at statement 3.
class Employee
{
};
class Project: public virtual Employee
{
};
class Salary: virtual public Employee
{
};
class Employee_Info: public Project, public Salary
{
};
Program is as follows :
class Employee { protected: char Emp_Name[10]; char dept[20]; public: void accept() { cout<<”Enter name of employee”; cin>>Emp_Name; cout<<”Enter department of employee”; cin>> dept; } }; class Project : public virtual Employee { protected: char Pro_name[10]; int Pro_id; public: void getdata() { cout<<”Enter name of project”; cin>>Pro_name; cout<<”Enter id of project”; cin>>Pro_id; } }; class Salary : virtual public Employee { protected: int amount; public: void acceptdata() { cout<<”Enter amount of salary”; cin>>amount; } }; class Emp_Info : public Project, public Salary { public: void display() { cout<<”Employee details are” cout<<”Name of employee is”<<Emp_Name; cout<<”Department of employee is”<<dept; cout<<”Name of Project is”<<Pro_name; cout<<” Id of Project is”<<Pro_id; cout<<”Salary of employee is”<<amount; } }; int main() { Emp_Info obj; obj.accept(); obj.getdata(); obj.acceptdata(); obj.display(); return 0; } | //Defines base class Employee
//Accept details of employee
//Defines sub class project that inherits Employee virtually
//Accept details of Project
//Accept details of salary
//Defines sub class Emp_Info
//Displays details of employee
//Defines main function
//Creates object of Emp_Info //Access member functions of classes to display details of employee. |
Output
Enter name of employee
John Mathew
Enter department of employee
Information Technology
Enter name of project
Employee Database
Enter id of project
11
Enter amount of salary
50000
Employee details are
Name of employee is: John Mathew
Department of employee is: Information Technology
Name of Project is: Employee Database
Id of Project is : 11
Salary of employee is: 50000
Virtual and public keywords can be used in either order.
Abstract class is a base class , all the concrete classes can inherit abstract class.
Characteristic of Abstract class.
class Abst
{
public:
virtual void show() = 0;
};
class Derived:public Abst
{
public:
void show()
{
cout << "This is the implementation of Virtual Function in Derived class\n";
}
};
int main()
{
Abst obj;
Abst *a;
Derived d;
a = &d;
a->show();
}
class A
{
friend class B;
};
Write a program to calculate area of cube and triangle using friend class
Solution :
#include <iostream>
using namespace std;
class cube; // Step 1 forward declaration
class Triangle {
int x,y;
public:
Triangle(int a,int b) // constructor
{
x=a;
y=b;
}
void display()
{
cout << "Area of triangle is " << ½*x*y << endl;
}
void area(cube &); // Step 2
};
class cube{
int s;
public:
cube(int p )
{
s=p;
}
void show()
{
cout << "Volume of cube is: " << s*s*s << endl;
}
friend class triangle; //Step 3 triangle is friend of class cube
};
void triangle::area(cube &p)
{
x = p.s; //Step 4
y = p.s;
}
int main () {
triangle T(10,5);
cube C(10);
T.display();
C.show();
T.area(C);
T.display();
C.show();
return 0;
}
Output
Area of triangle is 25
Volume of cube is 1000
Area of triangle is 50
Volume of cube is 1000
A nested class is a class that is declared in another class. The nested class is also a member variable of the enclosing class and has the same access rights as the other members. However, the member functions of the enclosing class have no special access to the members of a nested class.
A program that demonstrates nested classes in C++ is as follows.
Example
#include<iostream>
using namespace std;
class A {
public:
class B {
private:
int num;
public:
void getdata(int n) {
num = n;
}
void putdata() {
cout<<"The number is "<<num;
}
};
};
int main() {
cout<<"Nested classes in C++"<< endl;
A :: B obj;
obj.getdata(9);
obj.putdata();
return 0;
}
Output
Nested classes in C++
The number is 9
In the above program, class B is defined inside the class A so it is a nested class. The class B contains a private variable num and two public functions getdata() and putdata(). The function getdata() takes the data and the function putdata() displays the data. This is given as follows.
class A {
public:
class B {
private:
int num;
public:
void getdata(int n) {
num = n;
}
void putdata() {
cout<<"The number is "<<num;
}
};
};
In the function main(), an object of the class A and class B is defined. Then the functions getdata() and putdata() are called using the variable obj. This is shown below.
cout<<"Nested classes in C++"<< endl;
A :: B obj;
obj.getdata(9);
obj.putdata();
The pointer in C++ language is a variable, it is also known as locator or indicator that points to an address of a value.
Advantage of pointer
1) Pointer reduces the code and improves the performance, it is used to retrieving strings, trees etc. and used with arrays, structures and functions.
2) We can return multiple values from function using pointer.
3) It makes you able to access any memory location in the computer's memory.
Usage of pointer
There are many usage of pointers in C++ language.
1) Dynamic memory allocation
In c language, we can dynamically allocate memory using malloc() and calloc() functions where pointer is used.
2) Arrays, Functions and Structures
Pointers in c language are widely used in arrays, functions and structures. It reduces the code and improves the performance.
Symbols used in pointer
Symbol | Name | Description |
& (ampersand sign) | Address operator | Determine the address of a variable. |
∗ (asterisk sign) | Indirection operator | Access the value of an address. |
Declaring a pointer
The pointer in C++ language can be declared using ∗ (asterisk symbol).
Pointer Example
Let's see the simple example of using pointers printing the address and value.
Output:
Address of number variable is:0x7ffccc8724c4
Address of p variable is:0x7ffccc8724c4
Value of p variable is:30
Pointer Program to swap 2 numbers without using 3rd variable
Output:
Before swap: ∗p1=20 ∗p2=10
After swap: ∗p1=10 ∗p2=20
How to Initialize Pointer in C Programming?
pointer = &variable;
Above is the syntax for initializing pointer variable in C.
Initialization of Pointer can be done using following 4 Steps :
[box]
[/box]
below example will clearly explain the initialization of Pointer Variable.
#include<stdio.h>
int main()
{
int a; // Step 1
int *ptr; // Step 2
a = 10; // Step 3
ptr = &a; // Step 4
return(0);
}
Explanation of Above Program :
Note :
[box]Pointers are always initialized before using it in the program[/box]
Example : Initializing Integer Pointer
#include<stdio.h>
int main()
{
int a = 10;
int *ptr;
ptr = &a;
printf("\nValue of ptr : %u",ptr);
return(0);
}
Output :
Value of ptr : 4001
C++ provides two pointer operators, which are (a) Address of Operator & and (b) Indirection Operator *.
A pointer is a variable that contains the address of another variable or you can say that a variable that contains the address of another variable is said to "point to" the other variable. A variable can be any data type including an object, structure or again pointer itself.
The . (dot) operator and the -> (arrow) operator are used to reference individual members of classes, structures, and unions.
The Address of Operator &
The & is a unary operator that returns the memory address of its operand. For example, if var is an integer variable, then &var is its address. This operator has the same precedence and right-to-left associativity as the other unary operators.
You should read the & operator as "the address of" which means &var will be read as "the address of var".
The Indirection Operator *
The second operator is indirection Operator *, and it is the complement of &. It is a unary operator that returns the value of the variable located at the address specified by its operand.
The following program executes the two operations
#include <iostream>
using namespace std;
int main () {
int var;
int *ptr;
int val;
var = 3000;
// take the address of var
ptr = &var;
// take the value available at ptr
val = *ptr;
cout << "Value of var :" << var << endl;
cout << "Value of ptr :" << ptr << endl;
cout << "Value of val :" << val << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Value of var :3000
Value of ptr :0xbff64494
Value of val :3000
What is Memory Management?
Memory management is a process of managing computer memory, assigning the memory space to the programs to improve the overall system performance.
Why is memory management required?
As we know that arrays store the homogeneous data, so most of the time, memory is allocated to the array at the declaration time. Sometimes the situation arises when the exact memory is not determined until runtime. To avoid such a situation, we declare an array with a maximum size, but some memory will be unused. To avoid the wastage of memory, we use the new operator to allocate the memory dynamically at the run time.
Memory Management Operators
In C language, we use the malloc() or calloc() functions to allocate the memory dynamically at run time, and free() function is used to deallocate the dynamically allocated memory. C++ also supports these functions, but C++ also defines unary operators such as new and delete to perform the same tasks, i.e., allocating and freeing the memory.
New operator
A new operator is used to create the object while a delete operator is used to delete the object. When the object is created by using the new operator, then the object will exist until we explicitly use the delete operator to delete the object. Therefore, we can say that the lifetime of the object is not related to the block structure of the program.
Syntax
The above syntax is used to create the object using the new operator. In the above syntax, 'pointer_variable' is the name of the pointer variable, 'new' is the operator, and 'data-type' defines the type of the data.
Example 1:
In the above example, 'p' is a pointer of type int.
Example 2:
In the above example, 'q' is a pointer of type float.
In the above case, the declaration of pointers and their assignments are done separately. We can also combine these two statements as follows:
Assigning a value to the newly created object
Two ways of assigning values to the newly created object:
We assign 45 to the newly created int object and 9.8 to the newly created float object.
Let's look at some examples.
How to create a single dimensional array
As we know that new operator is used to create memory space for any data-type or even user-defined data type such as an array, structures, unions, etc., so the syntax for creating a one-dimensional array is given below:
Examples:
In the above statement, we have created an array of type int having a size equal to 8 where p[0] refers first element, p[1] refers the first element, and so on.
Delete operator
When memory is no longer required, then it needs to be deallocated so that the memory can be used for another purpose. This can be achieved by using the delete operator, as shown below:
In the above statement, 'delete' is the operator used to delete the existing object, and 'pointer_variable' is the name of the pointer variable.
In the previous case, we have created two pointers 'p' and 'q' by using the new operator, and can be deleted by using the following statements:
The dynamically allocated array can also be removed from the memory space by using the following syntax:
In the above statement, we need to specify the size that defines the number of elements that are required to be freed. The drawback of this syntax is that we need to remember the size of the array. But, in recent versions of C++, we do not need to mention the size as follows:
Let's understand through a simple example:
In the above code, we have created an array using the new operator. The above program will take the user input for the size of an array at the run time. When the program completes all the operations, then it deletes the object by using the statement delete arr.
Output
Advantages of the new operator
The following are the advantages of the new operator over malloc() function:
Classname Pointername;
Eg. Demo *P;
class employee
{
int id;
float salary;
public:
void accept()
{
cout<<”Enter details of employee”;
cin>>id>>salary;
}
void display()
{
cout<<”Employee’s id :”<<id;
cout<<”Employee’s salary :”<<salary;
}
};
Demo O;
Demo *P=&O;
P->accept();
P->display();
class Student { int rollno; double marks; public: Student( int x, double y) // Step1 { rollno=x; marks=y; } void display() { cout<<“Name”<<name; cout<<“Rollno”<<rollno; } }; void main() { Student S(1,70); // Step2 S.display(); // Step 3 } |
Step 1 : Member functions or constructor can access data members directly without any object. See step 1.
rollno=x;
marks=y;
Actually these statements means that x is copied to copy of rollno of invoking object. So it can be written as
this->rollno = x;
this->marks = y;
where “this” pointer points to invoking object.
Writing “this” is not mandatory as it is automatically passed implicitly to invoking object.
Step 2 : Here object of Student is S. Hence here invoking object is S. Thus in statement S(1,70), “this” points to “S”.
Student S (1,70);
Step 3 : In S.display() “this” points to S. If we create another object P and write P.display();then “this” will point to P.
S.display();
Pointers and arrays are strongly related. In fact, pointers and arrays are interchangeable in many cases. For example, a pointer that points to the beginning of an array can access that array by using either pointer arithmetic or array-style indexing. Consider the following program −
#include <iostream>
using namespace std;
const int MAX = 3;
int main () {
int var[MAX] = {10, 100, 200};
int *ptr;
// let us have array address in pointer.
ptr = var;
for (int i = 0; i < MAX; i++) {
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// point to the next location
ptr++;
}
return 0;
}
When the above code is compiled and executed, it produces result something as follows −
Address of var[0] = 0xbfa088b0
Value of var[0] = 10
Address of var[1] = 0xbfa088b4
Value of var[1] = 100
Address of var[2] = 0xbfa088b8
Value of var[2] = 200
However, pointers and arrays are not completely interchangeable. For example, consider the following program −
#include <iostream>
using namespace std;
const int MAX = 3;
int main () {
int var[MAX] = {10, 100, 200};
for (int i = 0; i < MAX; i++) {
*var = i; // This is a correct syntax
var++; // This is incorrect.
}
return 0;
}
It is perfectly acceptable to apply the pointer operator * to var but it is illegal to modify var value. The reason for this is that var is a constant that points to the beginning of an array and can not be used as l-value.
Because an array name generates a pointer constant, it can still be used in pointer-style expressions, as long as it is not modified. For example, the following is a valid statement that assigns var[2] the value 500 −
*(var + 2) = 500;
Above statement is valid and will compile successfully because var is not changed.
Pointers store the memory location or address of variables. In other words, pointers reference a memory location and obtaining the value stored at that memory location is known as dereferencing the pointer.
A program that uses pointers to access a single element of an array is given as follows −
Example
#include <iostream>
using namespace std;
int main() {
int arr[5] = {5, 2, 9, 4, 1};
int *ptr = &arr[2];
cout<<"The value in the second index of the array is: "<< *ptr;
return 0;
}
Output
The value in the second index of the array is: 9
In the above program, the pointer ptr stores the address of the element at the third index in the array i.e 9.
This is shown in the following code snippet.
int *ptr = &arr[2];
The pointer is dereferenced and the value 9 is displayed by using the indirection (*) operator. This is demonstrated as follows.
cout<<"The value in the second index of the array is: "<< *ptr;
Another program in which a single pointer is used to access all the elements of the array is given as follows.
Example
#include <iostream>
using namespace std;
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = &arr[0];
cout<<"The values in the array are: ";
for(int i = 0; i < 5; i++) {
cout<< *ptr <<" ";
ptr++;
}
return 0;
}
Output
The values in the array are: 1 2 3 4 5
In the above program, the pointer ptr stores the address of the first element of the array. This is done as follows.
int *ptr = &arr[0];
After this, a for loop is used to dereference the pointer and print all the elements in the array. The pointer is incremented in each iteration of the loop i.e at each loop iteration, the pointer points to the next element of the array. Then that array value is printed. This can be seen in the following code snippet.
for(int i = 0; i < 5; i++) {
cout<< *ptr <<" ";
ptr++;
}
Array and pointers are closely related to each other. In C++, the name of an array is considered às a pointer, i.e., the name of an array contains the address of an element. C++ considers the array name as the address of the first element. For example, if we create an array, i.e., marks which hold the 20 values of integer type, then marks will contain the address of first element, i.e., marks[0]. Therefore, we can say that array name (marks) is a pointer which is holding the address of the first element of an array.
Let's understand this scenario through an example.
In the above code, we declare an integer pointer and an array of integer type. We assign the address of marks to the ptr by using the statement ptr=marks; it means that both the variables 'marks' and 'ptr' point to the same element, i.e., marks[0]. When we try to print the values of *ptr and *marks, then it comes out to be same. Hence, it is proved that the array name stores the address of the first element of an array.
Output
Array of Pointers
An array of pointers is an array that consists of variables of pointer type, which means that the variable is a pointer addressing to some other element. Suppose we create an array of pointer holding 5 integer pointers; then its declaration would look like:
In the above declaration, we declare an array of pointer named as ptr, and it allocates 5 integer pointers in memory.
The element of an array of a pointer can also be initialized by assigning the address of some other element. Let's observe this case through an example.
In the above code, we are assigning the address of 'a' variable to the third element of an array 'ptr'.
We can also retrieve the value of 'a' be dereferencing the pointer.
Let's understand through an example.
In the above code, we declare an array of integer type and an array of integer pointers. We have defined the 'for' loop, which iterates through the elements of an array 'ptr1', and on each iteration, the address of element of ptr1 at index 'i' gets stored in the ptr2 at index 'i'.
Output
Till now, we have learnt the array of pointers to an integer. Now, we will see how to create the array of pointers to strings.
Array of Pointer to Strings
An array of pointer to strings is an array of character pointers that holds the address of the first character of a string or we can say the base address of a string.
The following are the differences between an array of pointers to string and two-dimensional array of characters:
Let's see how to declare the array of pointers to string.
First, we declare the array of pointer to string:
In the above code, we declared an array of pointer names as 'names' of size 5. In the above case, we have done the initialization at the time of declaration, so we do not need to mention the size of the array of a pointer. The above code can be re-written as:
In the above case, each element of the 'names' array is a string literal, and each string literal would hold the base address of the first character of a string. For example, names[0] contains the base address of "john", names[1] contains the base address of "Peter", and so on. It is not guaranteed that all the string literals will be stored in the contiguous memory location, but the characters of a string literal are stored in a contiguous memory location.
Let's create a simple example.
In the above code, we have declared an array of char pointer holding 5 string literals, and the first character of each string is holding the base address of the string.
Output
A function pointer is a variable that stores the address of a function that can later be called through that function pointer. This is useful because functions encapsulate behavior. For instance, every time you need a particular behavior such as drawing a line, instead of writing out a bunch of code, all you need to do is call the function. But sometimes you would like to choose different behaviors at different times in essentially the same piece of code. Read on for concrete examples.
Example Uses of Function Pointers
Functions as Arguments to Other Functions
If you were to write a sort routine, you might want to allow the function's caller to choose the order in which the data is sorted; some programmers might need to sort the data in ascending order, others might prefer descending order while still others may want something similar to but not quite like one of those choices. One way to let your user specify what to do is to provide a flag as an argument to the function, but this is inflexible; the sort function allows only a fixed set of comparison types (e.g., ascending and descending).
A much nicer way of allowing the user to choose how to sort the data is simply to let the user pass in a function to the sort function. This function might take two pieces of data and perform a comparison on them. We'll look at the syntax for this in a bit.
Callback Functions
Another use for function pointers is setting up "listener" or "callback" functions that are invoked when a particular event happens. The function is called, and this notifies your code that something of interest has taken place.
Why would you ever write code with callback functions? You often see it when writing code using someone's library. One example is when you're writing code for a graphical user interface (GUI). Most of the time, the user will interact with a loop that allows the mouse pointer to move and that redraws the interface. Sometimes, however, the user will click on a button or enter text into a field. These operations are "events" that may require a response that your program needs to handle. How can your code know what's happening? Using Callback functions! The user's click should cause the interface to call a function that you wrote to handle the event.
To get a sense for when you might do this, consider what might happen if you were using a GUI library that had a "create_button" function. It might take the location where a button should appear on the screen, the text of the button, and a function to call when the button is clicked. Assuming for the moment that C (and C++) had a generic "function pointer" type called function, this might look like this:
void create_button( int x, int y, const char *text, function callback_func );
Whenever the button is clicked, callback_func will be invoked. Exactly what callback_func does depends on the button; this is why allowing the create_button function to take a function pointer is useful.
Function Pointer Syntax
The syntax for declaring a function pointer might seem messy at first, but in most cases it's really quite straight-forward once you understand what's going on. Let's look at a simple example:
void (*foo)(int);
In this example, foo is a pointer to a function taking one argument, an integer, and that returns void. It's as if you're declaring a function called "*foo", which takes an int and returns void; now, if *foo is a function, then foo must be a pointer to a function. (Similarly, a declaration like int *x can be read as *x is an int, so x must be a pointer to an int.)
The key to writing the declaration for a function pointer is that you're just writing out the declaration of a function but with (*func_name) where you'd normally just put func_name.
Reading Function Pointer Declarations
Sometimes people get confused when more stars are thrown in:
void *(*foo)(int *);
Here, the key is to read inside-out; notice that the innermost element of the expression is *foo, and that otherwise it looks like a normal function declaration. *foo should refer to a function that returns a void * and takes an int *. Consequently, foo is a pointer to just such a function.
Initializing Function Pointers
To initialize a function pointer, you must give it the address of a function in your program. The syntax is like any other variable:
#include <stdio.h>
void my_int_func(int x)
{
printf( "%d\n", x );
}
int main()
{
void (*foo)(int);
/* the ampersand is actually optional */
foo = &my_int_func;
return 0;
}
(Note: all examples are written to be compatible with both C and C++.)
Using a Function Pointer
To call the function pointed to by a function pointer, you treat the function pointer as though it were the name of the function you wish to call. The act of calling it performs the dereference; there's no need to do it yourself:
#include <stdio.h>
void my_int_func(int x)
{
printf( "%d\n", x );
}
int main()
{
void (*foo)(int);
foo = &my_int_func;
/* call my_int_func (note that you do not need to write (*foo)(2) ) */
foo( 2 );
/* but if you want to, you may */
(*foo)( 2 );
return 0;
}
Note that function pointer syntax is flexible; it can either look like most other uses of pointers, with & and *, or you may omit that part of syntax. This is similar to how arrays are treated, where a bare array decays to a pointer, but you may also prefix the array with & to request its address.
Function Pointers in the Wild
Let's go back to the sorting example where I suggested using a function pointer to write a generic sorting routine where the exact order could be specified by the programmer calling the sorting function. It turns out that the C function qsort does just that.
From the Linux man pages, we have the following declaration for qsort (from stdlib.h):
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
Note the use of void*s to allow qsort to operate on any kind of data (in C++, you'd normally use templates for this task, but C++ also allows the use of void* pointers) because void* pointers can point to anything. Because we don't know the size of the individual elements in a void* array, we must give qsort the number of elements, nmemb, of the array to be sorted, base, in addition to the standard requirement of giving the length, size, of the input.
But what we're really interested in is the compar argument to qsort: it's a function pointer that takes two void *s and returns an int. This allows anyone to specify how to sort the elements of the array base without having to write a specialized sorting algorithm. Note, also, that compar returns an int; the function pointed to should return -1 if the first argument is less than the second, 0 if they are equal, or 1 if the second is less than the first.
For instance, to sort an array of numbers in ascending order, we could write code like this:
#include <stdlib.h>
int int_sorter( const void *first_arg, const void *second_arg )
{
int first = *(int*)first_arg;
int second = *(int*)second_arg;
if ( first < second )
{
return -1;
}
else if ( first == second )
{
return 0;
}
else
{
return 1;
}
}
int main()
{
int array[10];
int i;
/* fill array */
for ( i = 0; i < 10; ++i )
{
array[ i ] = 10 - i;
}
qsort( array, 10 , sizeof( int ), int_sorter );
for ( i = 0; i < 10; ++i )
{
printf ( "%d\n" ,array[ i ] );
}
}
Using Polymorphism and Virtual Functions Instead of Function Pointers (C++)
You can often avoid the need for explicit function pointers by using virtual functions. For instance, you could write a sorting routine that takes a pointer to a class that provides a virtual function called compare:
class Sorter
{
public:
virtual int compare (const void *first, const void *second);
};
// cpp_qsort, a qsort using C++ features like virtual functions
void cpp_qsort(void *base, size_t nmemb, size_t size, Sorter *compar);
inside cpp_qsort, whenever a comparison is needed, compar->compare should be called. For classes that override this virtual function, the sort routine will get the new behavior of that function. For instance:
class AscendSorter : public Sorter
{
virtual int compare (const void*, const void*)
{
int first = *(int*)first_arg;
int second = *(int*)second_arg;
if ( first < second )
{
return -1;
}
else if ( first == second )
{
return 0;
}
else
{
return 1;
}
}
};
and then you could pass in a pointer to an instance of the AscendSorter to cpp_qsort to sort integers in ascending order.
But Are You Really Not Using Function Pointers?
Virtual functions are implemented behind the scenes using function pointers, so you really are using function pointers--it just happens that the compiler makes the work easier for you. Using polymorphism can be an appropriate strategy (for instance, it's used by Java), but it does lead to the overhead of having to create an object rather than simply pass in a function pointer.
Function Pointers Summary
Syntax
DeclaringDeclare a function pointer as though you were declaring a function, except with a name like *foo instead of just foo:
void (*foo)(int);
InitializingYou can get the address of a function simply by naming it:
void foo();
func_pointer = foo;
or by prefixing the name of the function with an ampersand:
void foo();
func_pointer = &foo;
InvokingInvoke the function pointed to just as if you were calling a function.
func_pointer( arg1, arg2 );
or you may optionally dereference the function pointer before calling the function it points to:
(*func_pointer)( arg1, arg2 );
Benefits of Function Pointers
A pointer to a pointer is a form of multiple in direction or a chain of pointers. Normally, a pointer contains the address of a variable. When we define a pointer to a pointer, the first pointer contains the address of the second pointer, which points to the location that contains the actual value as shown below.
A variable that is a pointer to a pointer must be declared as such. This is done by placing an additional asterisk in front of its name. For example, following is the declaration to declare a pointer to a pointer of type int −
int **var;
When a target value is indirectly pointed to by a pointer to a pointer, accessing that value requires that the asterisk operator be applied twice, as is shown below in the example −
#include <iostream>
using namespace std;
int main () {
int var;
int *ptr;
int **pptr;
var = 3000;
// take the address of var
ptr = &var;
// take the address of ptr using address of operator &
pptr = &ptr;
// take the value using pptr
cout << "Value of var :" << var << endl;
cout << "Value available at *ptr :" << *ptr << endl;
cout << "Value available at **pptr :" << **pptr << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Value of var :3000
Value available at *ptr :3000
Value available at **pptr :3000
#include<iostream>
using namespace std;
class A
{
protected:
int x;
void display()
{
cout<<x<<endl;
}
};
class B :A
{
protected:
int y;
void display()
{
cout<<”/tx=”<<x<<”/ty= ”<<y<<endl;
}
};
int main()
{
B *P; // Pointer to derived class
B obj;
P= &obj;
P->x=10; //access base class member
P->y=20; //access derived class member
P->display(); // calls display() of derived class
return 0;
}
Output
x= 10 y=20
Pointer to derived class can access both base and derived class members.
C++ allows you to pass a pointer to a function. To do so, simply declare the function parameter as a pointer type.
Following a simple example where we pass an unsigned long pointer to a function and change the value inside the function which reflects back in the calling function −
#include <iostream>
#include <ctime>
using namespace std;
void getSeconds(unsigned long *par);
int main () {
unsigned long sec;
getSeconds( &sec );
// print the actual value
cout << "Number of seconds :" << sec << endl;
return 0;
}
void getSeconds(unsigned long *par) {
// get the current number of seconds
*par = time( NULL );
return;
}
When the above code is compiled and executed, it produces the following result −
Number of seconds :1294450468
The function which can accept a pointer, can also accept an array as shown in the following example −
#include <iostream>
using namespace std;
// function declaration:
double getAverage(int *arr, int size);
int main () {
// an int array with 5 elements.
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
// pass pointer to the array as an argument.
avg = getAverage( balance, 5 ) ;
// output the returned value
cout << "Average value is: " << avg << endl;
return 0;
}
double getAverage(int *arr, int size) {
int i, sum = 0;
double avg;
for (i = 0; i < size; ++i) {
sum += arr[i];
}
avg = double(sum) / size;
return avg;
}
When the above code is compiled together and executed, it produces the following result −
Average value is: 214.4
As we have seen in last chapter how C++ allows to return an array from a function, similar way C++ allows you to return a pointer from a function. To do so, you would have to declare a function returning a pointer as in the following example −
int * myFunction() {
.
.
.
}
Second point to remember is that, it is not good idea to return the address of a local variable to outside of the function, so you would have to define the local variable as static variable.
Now, consider the following function, which will generate 10 random numbers and return them using an array name which represents a pointer i.e., address of first array element.
#include <iostream>
#include <ctime>
using namespace std;
// function to generate and retrun random numbers.
int * getRandom( ) {
static int r[10];
// set the seed
srand( (unsigned)time( NULL ) );
for (int i = 0; i < 10; ++i) {
r[i] = rand();
cout << r[i] << endl;
}
return r;
}
// main function to call above defined function.
int main () {
// a pointer to an int.
int *p;
p = getRandom();
for ( int i = 0; i < 10; i++ ) {
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
return 0;
}
When the above code is compiled together and executed, it produces result something as follows −
624723190
1468735695
807113585
976495677
613357504
1377296355
1530315259
1778906708
1820354158
667126415
*(p + 0) : 624723190
*(p + 1) : 1468735695
*(p + 2) : 807113585
*(p + 3) : 976495677
*(p + 4) : 613357504
*(p + 5) : 1377296355
*(p + 6) : 1530315259
*(p + 7) : 1778906708
*(p + 8) : 1820354158
*(p + 9) : 667126415
Null pointer
It is always a good practice to assign the pointer NULL to a pointer variable in case you do not have exact address to be assigned. This is done at the time of variable declaration. A pointer that is assigned NULL is called a null pointer.
The NULL pointer is a constant with a value of zero defined in several standard libraries, including iostream. Consider the following program −
#include <iostream>
using namespace std;
int main () {
int *ptr = NULL;
cout << "The value of ptr is " << ptr ;
return 0;
}
When the above code is compiled and executed, it produces the following result −
The value of ptr is 0
On most of the operating systems, programs are not permitted to access memory at address 0 because that memory is reserved by the operating system. However, the memory address 0 has special significance; it signals that the pointer is not intended to point to an accessible memory location. But by convention, if a pointer contains the null (zero) value, it is assumed to point to nothing.
To check for a null pointer you can use an if statement as follows −
if(ptr) // succeeds if p is not null
if(!ptr) // succeeds if p is null
Thus, if all unused pointers are given the null value and you avoid the use of a null pointer, you can avoid the accidental misuse of an uninitialized pointer. Many times, uninitialized variables hold some junk values and it becomes difficult to debug the program.
Void pointer
References:
1. Herbert Schildt, ―C++ The complete reference‖, Eighth Edition, McGraw Hill Professional, 2011, ISBN:978-00-72226805
2. Matt Weisfeld, ―The Object-Oriented Thought Process, Third Edition Pearson ISBN-13:075- 2063330166
3. Cox Brad, Andrew J. Novobilski, ―Object –Oriented Programming: An EvolutionaryApproach‖, Second Edition, Addison–Wesley, ISBN:13:978-020-1548341
4. Deitel, “C++ How to Program”, 4th Edition, Pearson Education, ISBN:81-297-0276-2