UNIT-II_OOP_RBK
UNIT-II_OOP_RBK
B
Derived / sub / child Class
MULTIPLE INHERITANCE
When a derived class inherit from multiple
base classes it is known as multiple
Inheritance.
A B Base Class
Derived Class
C
MULTILEVEL INHERITANCE
When a derived class inherit from a class that
itself inherits from other class , it is known as
multilevel Inheritance.
A
Base Class
Derived Class of A
B Base Class of C
Derived Class
C
HIERARCHICAL INHERITANCE
When many derived classes inherit from a
single base class , it is known as
hierarchical Inheritance.
A Base Class
B C D
Derived classes
HYBRID INHERITANCE
Hybrid Inheritance combines two or more forms
of Inheritance.
A
B C
D
DEFINING DERIVED CLASS
A general form to defining a derived class is:
Class derived_class_name : visibility_mode base_class_name
{
members of derived class
} ;
Example :
Class A
Base Derived
Base Derived
Base Class
Visibility Public Private Protected
derivation derivation derivation
Private Yes No No
class MyClass { // The class
public: // Access specifier
// class members goes here
};
class MyClass {
int x; // Private attribute
int y; // Private attribute
};
PROGRAM: 1
#include <iostream>
using namespace std;
class MyClass {
public: // Public access specifier
int x; // Public attribute
private: // Private access specifier
int y; // Private attribute
};
int main() {
MyClass myObj;
myObj.x = 25; // Allowed (x is public)
myObj.y = 50; // Not allowed (y is private)
return 0;
}
Output:
In function 'int main()':
Line 8: error: 'int MyClass::y' is private
Line 14: error: within this context
PROGRAM: 2 #include <iostream>
using namespace std;
// Parent class
class MyClass {
public:
void myFunction() {
cout << "Some content in parent class." ;
}
};
// Child class
class MyChild: public MyClass {
};
// Grandchild class
class MyGrandChild: public MyChild {
};
int main() {
MyGrandChild myObj;
myObj.myFunction();
return 0;
}
Output:
// Base class
class MyClass { int main() {
public: MyChildClass myObj;
void myFunction() { myObj.myFunction();
cout << "Some content in parent class.\n" ; myObj.myOtherFunction();
} return 0;
}; }
// Derived class
class MyChildClass: public MyClass, public
MyOtherClass {
};
Constructors and Destructors in Derived
Classes
• Invocation of constructors and destructors
depends on the type of inheritance being
implemented. We have presented you the
sequence in which constructors and
destructors get called in single and multiple
inheritance.
• When we are using the constructors and
destructors in the inheritance, parent class
constructors and destructors are accessible to
the child class hence when we create an
object for the child class, constructors and
destructors of both parent and child class get
executed.
Constructors and Destructors in Derived
Classes
• Constructor and destructor in single
inheritance
• Base class constructors are called first and the
derived class constructors are called next in
single inheritance.
• Destructor is called in reverse sequence of
constructor invocation i.e. The destructor of
the derived class is called first and the
destructor of the base is called next.
Single Inheritance:
int main()
#include <iostream> {
using namespace std; derived ob;
return 0;
};
}
class derived1 : public base {
public: Output:
derived1() { cout << "Constructing Constructing base
derived1\n"; } Constructing derived1
Constructing derived2
~derived1() { cout << "Destructing Destructing derived2
derived1\n"; } Destructing derived1
}; Destructing base
Constructing base1 Constructing base2 Constructing derived Destructing derived Destructing base2 Destructing base1
Inheritance: Multiple base classes class derived: public base1, public
#include <iostream> base2 {
public:
using namespace std;
derived() { cout << "Constructing
class base1 { derived\n"; }
public: ~derived() { cout << "Destructing
base1() { cout << "Constructing derived\n"; }
base1\n"; } };
int main()
~base1() { cout << "Destructing
{
base1\n"; } derived ob;
}; // construct and destruct ob
return 0;
class base2 { }
Output:
public:
Constructing base1
base2() { cout << "Constructing Constructing base2
base2\n"; } Constructing derived
~base2() { cout << "Destructing Destructing derived
base2\n"; } Destructing base2
Destructing base1
};
Constructor and Destructor in Multiple
Inheritance
class Parent
{
int x;
public:
// base class's parameterized constructor
Parent(int i)
{
x = i;
cout << "Inside base class's parameterized constructor" << endl;
}
};
// sub class
class Child : public Parent {
public:
// sub class's parameterized constructor
Child(int x): Parent(x)
{
cout << "Inside sub class's parameterized constructor"<< endl;
}
};
// main function
int main()
{
// creating object of class Child
Child obj1(10);
return
Output:0;
}
Inside base class's parameterized constructor
Inside sub class's parameterized constructor
C++ program:
#include<iostream> A2()
using namespace std; {
int x = 50, y = 42, z;
class A1
z = x - y;
{ cout << "Difference is:" <<
public: z << endl;
A1() }
{ };
int a = 20, b = 35, c; class S: public A1,virtual A2
{
c = a + b;
public:
cout << "Sum is:" << S(): A1(), A2()
c << endl; {
} int r = 40, s = 8, t;
}; t = r * s;
class A2 cout << "Product is:" <<
t << endl;
{
}
public: };
// Driver code
int main()
{
S obj;
return 0;
}
Output
Difference is:8
Sum is:55
Product is:320
C++ program to implement constructors
in multiple inheritance class D : public B, public C {
#include <iostream> };
using namespace std;
int main()
{
class A { D object;
public: object.show();
void show() }
{
cout << "Hello form A \n"; Output:
prog.cpp: In function 'int main()':
}
prog.cpp:29:9: error: request for
}; member 'show' is ambiguous
object.show();
class B : public A { ^
}; prog.cpp:8:8: note: candidates are:
void A::show()
void show()
class C : public A {
^
}; prog.cpp:8:8: note: void
A::show()
How to resolve this issue?
To resolve this ambiguity when class A is inherited in both class B and class
C, it is declared as virtual base class by placing a keyword virtual as :
Syntax for Virtual Base Classes:
Syntax 1:
class B : virtual public A
{
};
Syntax 2:
class C : public virtual A
{
};
virtual can be written before or after the public. Now only one copy of data,
function member will be copied to class C and class B and class A becomes
the virtual base class. Virtual base classes offer a way to save space and
avoid ambiguities in class hierarchies that use multiple inheritances. When a
base class is specified as a virtual base, it can act as an indirect base more
than once without duplication of its data members. A single copy of its data
members is shared by all the base classes that use virtual base.
C++ program: class D : public B, public C {
};
#include <iostream>
using namespace std; int main()
class A { {
D object; // object creation of class d
public:
cout << "a = " << object.a << endl;
int a;
A() // constructor return 0;
{ }
a = 10;
} Output
a = 10
};
enum enumerated-type-name
{
value1, value2, value3…..valueN
};
// C++ Program to Demonstrate the Functioning of Enumerators with an example of Gender
#include <bits/stdc++.h>
using namespace std;
int main()
{
// Defining enum Gender
enum Gender { Male, Female };
int main() {
string food = "Pizza";
Output:
Pizza
0x6dfed4
Program
#include <iostream>
#include <string>
using namespace std;
int main() {
string food = "Pizza"; // A string variable
string* ptr = &food; // A pointer variable that stores the address of food
int main() {
string food = "Pizza"; // Variable declaration
string* ptr = &food; // Pointer declaration
OR
• Syntax;
new data type;
data-type could be any built-in data type
including an array or any user defined data
types include class or structure.
e.g.
double* pvalue = NULL; // Pointer initialized
with null
pvalue = new double; // Request memory for
the variable
int * p2; // Not initialize, points to somewhere which
is invalid
cout << p2 << endl; // Print address before allocation
p2 = new int; // Dynamically allocate an int and
assign its address to pointer // The pointer gets a
valid address with memory allocated
*p2 = 99;
cout << p2 << endl; // Print address after allocation
cout << *p2 << endl; // Print value point-to
delete p2; // Remove the dynamically allocated
storage
The new operator:
The new operator requests for the memory allocation in heap. If
the sufficient memory is available, it initializes the memory to
the pointer variable and returns its address.
cout << "Value of pointer variable 1 : " << ptr1 << endl;
cout << "Value of pointer variable 2 : " << ptr2 << endl;
cout << "Value of pointer variable 1 : " << *ptr1 << endl;
cout << "Value of pointer variable 2 : " << *ptr2 << endl;
cout << "Value of pointer variable 3 : " << ptr3 << endl;
cout << "Value of pointer variable 3 : " << *ptr3 << endl;
• Output:
Value of pointer variable 1 : 0x871eb0
Value of pointer variable 2 : 0x871ed0
Value of pointer variable 1 : 28
Value of pointer variable 2 : 223.324
Value of pointer variable 3 : 0x871ef0
Value of pointer variable 3 : 0
The delete operator
The delete operator is used to deallocate the memory.
User has privilege to deallocate the created pointer
variable by this delete operator.
delete pointer_variable;
Here is the syntax to delete the block of allocated
memory,
delete[ ] pointer_variable;
//delete operator:
#include <iostream>
using namespace std;
int main () {
int *ptr1 = NULL;
ptr1 = new int;
float *ptr2 = new float(299.121);
int *ptr3 = new int(30);
*ptr1 = 28;
cout << "Value of pointer variable 1 : " << *ptr1 << endl;
cout << "Value of pointer variable 2 : " << *ptr2 << endl;
cout << "Value of pointer variable 3 : " << *ptr3 << endl;
delete ptr1;
delete ptr2;
delete[] ptr3;
cout << "Value of pointer variable 1 : " << *ptr1 << endl;
cout << "Value of pointer variable 2 : " << *ptr2 << endl;
cout << "Value of pointer variable 3 : " << *ptr3 << endl;
return 0;
}
• Output:
Value of pointer variable 1 : 28
Value of pointer variable 2 : 299.121
Value of pointer variable 3 : 30
Value of pointer variable 1 : 0
Value of pointer variable 2 : -2.42212e+09
Value of pointer variable 3 : -821010736
Pointers to Objects
• You can access an object either directly, or by using
a pointer to the object.
• To access an element of an object when using the
actual object itself, use the dot operator.
• To access a specific element of an object when
using a pointer to the object, you must use the
arrow operator.
• To declare an object pointer, you use the same
declaration syntax that you would use for any other
pointer type.
Pointers to Objects
student st; 51, Rajesh
st
ptr 2FCD54
Pointers to Objects
• Pointers can be defined to hold the address of an
object, which is created statically or dynamically
Example:
stp st_name;
stp read_data ( );
// A simple example using an object int main()
pointer. {
My_Class ob, *p; // declare an object and
#include <iostream> pointer to it
using namespace std;
ob.set_num(1); // access ob directly
ob.show_num();
class My_Class {
int num; p = &ob; // assign p the address of ob
public: p->show_num(); // access ob using pointer
void set_num(int val) {num = val;}
void show_num(); return 0;
}; }
Output:
void My_Class::show_num() 1
{ 1
cout << num << "\n";
}
The this Pointer
• The this pointer points to the object that
invoked the function
2. Collection of elements of similar data type. Store the address of another variable.
The size of the array decides the number of The pointer can store the address of
4.
elements it can store. only one variable.
Arrays are static in nature i.e. they cannot be Pointers are dynamic in nature i.e.
7.
resized according to the user requirements. memory allocated can be resized later.
*(P + 1):
P = 1000 and 1 = sizeof(int) = 4 bytes.
Hence, *(1004) and dereferencing by * (asterisk) symbol. Now,
the final result is 38.
*(P) + 1:
P = 1000
Hence, *(1000) and dereferencing by * (asterisk) symbol and
then by adding 1 modifies the result to 23 + 1 = 24.
// C++ program to illustrate the // Print the values using pointers
concepts cout << *p << endl;
cout << *p + 1 << endl;
// of creating 1D array of pointers
cout << *(p + 1) << endl;
#include <iostream> cout << 2[p] << endl;
using namespace std; cout << p[2] << endl;
int main() cout << 3[p] << endl;
{ cout << p[4] << endl;
// Dynamically creating the array *p++;
// Pointing to next location
// of size = 5
cout << *p;
int* p = new int[5];
return 0;
// Initialize the array p[] as }
// {10, 20, 30, 40, 50}
for (int i = 0; i < 5; i++) {
p[i] = 10 * (i + 1);
}
Output
• 10
• 11
• 20
• 30
• 30
• 40
• 50
• 20
Dynamic 2D Array of Pointers in C++:
• A dynamic array of pointers is basically an array of
pointers where every array index points to a memory
block. This represents a 2D view in our mind. But
logically it is a continuous memory block.
• Syntax:<dataType> **<Pointer name> = new
<dataType> *[<size>];
• Ex: int **P = new int *[4];
• The *(asterisk) symbol defines the level of the pointer,
one * means one level of pointers, where ** implies
two levels of pointers, and so on. Also, the level of the
pointer must be the same as the dimensional array
you want to create dynamically.
Pointers to pointers
• A pointer to a pointer is a form of multiple
indirection 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.
• Int **var;
Approach: Create a 1D array of pointers.
1-D Array
*P is equal to P[0] which is the address of the 1st row, 1st column is &P[0][0] = 3000.
*(P + 1) is equal to ‘P‘ is 1000 + 1(sizeof int) = 1004 and * means dereferencing. So
the value stored at the address is printed i.e., *1004 = 4000.
*(P + 1) + 2 is same as above case but +2 means (&P[1] + 2) is equal to &P[1] [2] =
4008.
*(*(P + 1) + 2) is same as above case but that first asterisk ‘*(….)’ means
dereferencing that address. Therefore, the result is equal to the value in &P[1][2] =
*(4008) = 54.
Pointers to pointers
// C program to demonstrate pointer to pointer
#include <iostream>
using namespace std;
int main ()
{
int var;
int *ptr;
int **pptr;
var = 3000;
ptr = &var;
pptr = &ptr;
cout << "Value of var :" << var << endl;
cout << "Value of ptr :" << ptr << endl;
cout << "Value available at *ptr :" << *ptr << endl;
cout << "Value available at pptr :" << pptr << endl;
cout << "Value available at **pptr :" << **pptr << endl;
return 0;
}
• Output:
Value of var :3000
Value of ptr :0x7ffe54d98a9c
Value available at *ptr :3000
Value available at pptr :0x7ffe54d98aa0
Value available at **pptr :3000
// C++ program to illustrate the // Creating N sized int memory
concepts // block
// of creating 2D array of pointers for (int j = 0; j < N; j++, x++) {
p[i][j] = 10 * x;
#include <iostream>
using namespace std; // The above statement can
// Driver Code // also be written as:
int main() // *(*(p+i)+j) = 10 * x
{ }
int N = 3; }
// Print the values using pointers
// Creating the array of pointers
cout << *p << endl;
// of size N cout << **p << endl;
int** p = new int*[N]; cout << *p + 1 << endl;
int x = 1; cout << **p + 1 << endl;
0x158de90
10
0x158de94
11
Function pointer
• Function pointers are similar, except that
instead of pointing to variables, they point to
functions!
• Syntax for Declaration
• The following is the syntax for the declaration
of a function pointer:
Int *ptr;
Int *ptr[5];
Int (*ptr)();
//Program for function pointer declaration
#include <iostream>
using namespace std;
int add(int a , int b)
{
return a+b;
}
int main()
{
int (*funcptr)(int,int); // function pointer declaration
funcptr=add; // funcptr is pointing to the add function
int sum=funcptr(5,5);
cout << "value of sum is :" <<sum<<endl;
return 0;
}
Output:
value of sum is :10
Null pointer
• 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.
Null pointer program:
#include <iostream>
using namespace std;
int main ()
{
int *ptr = NULL;
cout << "The value of ptr is " << ptr ;
return 0;
}
int main()
{
int a = 10;
char b = 'x';
Output:
error: ‘void*’ is not a pointer-to-object type
12 | cout<<*p<<endl;
Void pointer program
#include <iostream>
using namespace std;
int main()
{
int a = 10;
char b = 'x';
Output:
0x7ffd25ba9374
0x7ffd25ba9373
Void pointer program
#include <iostream>
using namespace std;
int main()
{
int a = 10;
char b = 'x';
Output:
0x7fff5575e717
10
Pointers to base class
• Pointer is a data type that stores the address
of other data types.
• The pointer of Base Class pointing different
object of derived class:
Approach:
void display()
{
cout << "Displaying Base class"
<< " variable var_base: " << var_base <<
endl;
}
};
class DerivedClass : public BaseClass {
public:
int var_derived;
void display()
{
cout << "Displaying Base class"
<< "variable var_base: " <<
// Driver Code
int main()
{
// Pointer to base class
BaseClass* base_class_pointer; return 0;
BaseClass obj_base; }
DerivedClass obj_derived;
// Pointing to derived class
base_class_pointer = &obj_derived;
base_class_pointer->var_base = 34;
base_class_pointer->var_base = 3400;
base_class_pointer->display();
DerivedClass* derived_class_pointer;
derived_class_pointer = &obj_derived;
derived_class_pointer->var_base = 9448;
derived_class_pointer->var_derived = 98;
derived_class_pointer->display();
Output:
Displaying Base class variable var_base: 34
Displaying Base class variable var_base:
3400
Displaying Base classvariable var_base: 9448
Displaying Derived class variable
var_derived: 98