OOP With C++

Download as pdf or txt
Download as pdf or txt
You are on page 1of 22

02/08/2020 OOP with C++ :

OOP with C++ :


For any improvements or suggestions, contact me

Namespaces

using namespace std; // what does this imply ? what is a namespace ? what is its

A namespace is a declarative region that provides a scope to the identifiers (the names
of types, functions, variables, etc) inside it. Namespaces are used to organise code into
logical groups and to prevent name collisions that can occur especially when your code
base includes multiple libraries.

The statement above simply says that we are using software components from the C++
standard library, such as when you are using cout, it is actually std::cout .

Inline Functions
Some functions are of quite small size, but quite frequently called. C++ provides an inline
functions to reduce the function call overhead. Inline function is a function that is expanded
in line when it is called. When the inline function is called whole code of the inline function
gets inserted or substituted at the point of inline function call. This substitution is
performed by the C++ compiler at compile time . Inline function may increase efficiency if it
is small. Know more here

For a function to be inline, it can't contain a loop, static variables, switch or goto statement.
Also, an inline function should not be recursive and if its return type is other than void
then, return statement should be present in function body. If the function definition of a
member function of a class is written inside the class itself, then that function is implicitly
inline.

Advantages of inline function

It also saves the overhead of push/pop variables on the stack when function is called.
It also saves overhead of a return call from a function

Reference variables
It is nothing but a different name (alias) for the same memory location . Eg.

https://app.simplenote.com/p/lSLzHg 1/22
02/08/2020 OOP with C++ :

int a=33;
int &b= a; /* Here, b is a reference for variable a DON'T CONFUSE THIS WITH POINT
cout << b; // output :- 33

Call by reference [ 2 methods ]


(A) Using pointers (similar to C) - Actually call by address Eg.

void swap (int * a, int * b)


{
int t;
t=*a;
*a=*b;
*b=t;
}

In main(), we pass the addresses of variables to swap, swap(&c,&d);

(B) Using reference variables A reference is declared by putting "&" in front of the identifier
in the function header . A reference is not a variable. It is just an alias of a variable. Eg.

void swap (int & a, int & b)


{
int t;
t=a;
a=b;
b=t;
}

In main(), just call normally, swap(c,d); (It will automatically pass by reference)

Default arguments to functions-


However, only the rightmost arguments can be omitted i.e. you can not provide the 1st and
3rd argument and omit the middle one

Eg.

float si (float principal, int r, int t=1 )


{
return t*r*principal;
}

https://app.simplenote.com/p/lSLzHg 2/22
02/08/2020 OOP with C++ :

In main(), call as si(33.00,2); It returns 66.00 taking default value of t as 1 because only 2
arguements are passed.

Polymorphism
Polymorphism is a feature of OOPs that allows an object to behave differently in
different conditions.

Types of polymorphism

Binding

For function calls, binding means matching the call with the right function definition
by the compiler. It takes place either at compile time or at runtime.

There are 2 types of binding :

i. Early Binding or static binding (Compile-time time polymorphism)

ii. Late Binding or dynamic binding (Run time polymorphism)

Function Overloading
Functions with the same name but different signature (i.e. argument list or parameter
list) are called overloaded functions. Overloaded functions are recognised by the
compiler through the argument list in the call.

Example

void area(int a); // for calculating area of circle


void area(int a, int b); // for calculating area of rectangle using the same func

https://app.simplenote.com/p/lSLzHg 3/22
02/08/2020 OOP with C++ :

Function pointer and call-back technique


Just like an array name is the address of the first array element, a function name is a
actually the starting address of the function code. For more, view here. Eg.

void fun(int a)
{
printf("Value of a is %d\n", a);
}

int main()
{
// fun_ptr is a pointer to function fun()
void (*fun_ptr)(int) = &fun; // Note the brackets

/* The above line is equivalent of following two


void (*fun_ptr)(int);
fun_ptr = &fun;
*/

// Invoking fun() using fun_ptr


(*fun_ptr)(10);

return 0;
}

Array of pointers to a function:-

(Only Useful in a menu-driven system, when all Functions have same signatures and
prototypes)

char (*funPtr[3])(int) = {fun1, fun2,fun3};


int choice = 0;

while(choice != -1)
{
(*funPtr[choice])();
cin >> choice;
}

Classes in C++:-
Class : It is a user-defined data type, which holds its own data members and member
functions, which can be accessed and used by creating an instance of that class. Class
acts as a blueprint for an object.

https://app.simplenote.com/p/lSLzHg 4/22
02/08/2020 OOP with C++ :

Object : An instance of a class, that has some properties (data members) and
behaviours (member functions) associated with it.

When a class is defined, no memory is allocated but when it is instantiated (i.e. an


object is created) memory is allocated.

There are 3 member access specifiers- public, private, protected All data members and
methods declared by the public specifier are accessible from outside, and all declared
by private are only accessible for methods.

If the method is defined inside the class body, it is automatically inlined. It may
improve the performance (As it avoids calling of function) , but it is not good for
information hiding, because the client of the object is able to see the implementation of
its methods.

To define the method outside the class body , you have to use scope resolution operator
::

Private and protected data members can also be changed by friends of its class.

Both structures and classes have private, public and protected access specifiers. Default
access specifier of classes is private, default for structure is public.

There are basically 5 types of member functions :-

1. Constructor (create an object with a legal initial value)

2. Access methods (getters and setters)

3. Service Methods (for services)

4. Utility Methods (private methods, which are called only by other methods of the same
class)

5. Destructor (Destroying or releasing memory occupied by an object)

Constructor and Destructor :-

Constructors

(A) There is a special method with the same name as the class called constructor . There is
no return type (even not void) for this special method. Constructors can be overloaded .

(B) 3 types of constructor:-

1. Default - No arguement Used mostly for creating an array of objects

2. Parameterized - has some arguements

https://app.simplenote.com/p/lSLzHg 5/22
02/08/2020 OOP with C++ :

3. Copy Constructor - has an argument its own type, to copy a new object out of it.

It uses Call by reference, Otherwise the copy constructor call results in infinite
recursion , because for call-by-value, a copy of the object passed to the copy constructor
must be made, which results in the copy constructor being called recursively

Also, The object argument passed to the copy constructor must be constant. Otherwise
it can not be applied on constant object. For more, view here

(C) When the user defines a parametrized Constructor, it hides the default constructor.

(D) If you want to have an array of objects that do not have a default constructor , the work-
around is to have an array of pointers and initialize them using operator new . See
examples here

(E) If copy constructor is not provided, compiler will provide a default copy constructor ,
which makes default memberwise copy, which can not deal with objects with pointer
members (it will perform only shallow copy of pointers) . As in C++, objects are passed by
value, by default , a copy constructor is generally required.

Note : This is different from JAVA where all objects are passed by reference and the
language even does not support automatic pass-by-value, there is no need for
enforcement of copy constructors. For the purpose of cloning objects, Java provides a
more robust and automated facility – the clone mechanism.

Destructors

(A) Automatically called when an object leave scope to release all resources held by the
object. The name of a destructor for a class is the tilde (~) character followed by the class
name. Stack memory resources held by the object such as its compiler-created members are
released automatically when the object leaves scope or explicitly deleted. A destructor is
only needed to release resources which can not be automatically released, such as
dynamically allocated memory (using "new") or network or database connection.

(B) Destructor is called when object goes out of scope .

(C) The order of calling of Constructor is just opposite to that of Destructors.

Operator Overloading
In C++, we can make operators to work for user defined classes. This means C++ has the
ability to provide the operators with a special meaning for a data type, this ability is
known as operator overloading.
For example, we can overload an operator ‘+’ in a class like String so that we can
concatenate two strings by just using +.

https://app.simplenote.com/p/lSLzHg 6/22
02/08/2020 OOP with C++ :

class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i =0) {real = r; imag = i;}

// This is automatically called when '+' is used with


// between two Complex objects
Complex operator + (Complex const &obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() { cout << real << " + i" << imag << endl; }
};

int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // An example call to "operator+"
c3.print();
}

Global operator overloading (using friend function)

Example

class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i =0) {real = r; imag = i;}
void print() { cout << real << " + i" << imag << endl; }

// The global operator function is made friend of this class so


// that it can access private members
friend Complex operator + (Complex const &, Complex const &);
};

Complex operator + (Complex const &c1, Complex const &c2)


{
return Complex(c1.real + c2.real, c1.imag + c2.imag);
}

For operator overloading :

the function call operator can't have default arguements

https://app.simplenote.com/p/lSLzHg 7/22
02/08/2020 OOP with C++ :

All operators except = are accessed by derived class

Operators ( ), [ ], -> , = can be overloaded only as member function ( not as friend


function)

In overloading Array index operator [] operator and -> operator, we need to return a
reference

For unary operators, the parameter list is empty except postfix + +, - - Eg.

void operator ++ (); // prefix


void operator ++ (int); // postfix

Advantage of using friend function for operator overloading is that - if we use member
function, during execution, it creates a temporary instance of objects and may result in
huge allocation of memory references

Operators that cannot be overloaded

Scope resolution operation (::)


Member access operators (*,.)
Ternary operator (? :)
Sizeof
Preprocessor directive (#)

Overloading operator << to print complex number-

Complex is a predefined class

ostream& operator << (ostream& out,Complex n){


out<<n.real;
if(n.img<0) out<<'-'<<'i';
else out<<'+'<<'i';
out<<(n.img<0? -(n.img): n.img);
return out;
}

Encapsulation
Encapsulation is defined as binding together the data and the functions that
manipulate them, in a single unit called class .
Encapsulation also leads to data abstraction or hiding.

https://app.simplenote.com/p/lSLzHg 8/22
02/08/2020 OOP with C++ :

Data hiding and data abstraction

Data Hiding

Data hiding refers to hiding internal object details (data members). Data hiding ensures
exclusive data access to class members and protects object integrity by preventing
unintended or intended data alteration (or data modification). This is one of the
important reason why OOP is preferred, nowadays.

Private members are implicitly visible ( enforce data hiding )

Data Abstraction

Data abstraction refers to providing only essential information about the data to the
outside world, hiding the background details or implementation.

Consider a real life example of a man driving a car. The man only knows that pressing
the accelerators will increase the speed of car or applying brakes will stop the car but
he does not know about how on pressing accelerator the speed is actually increasing,
he does not know about the inner mechanism of the car or the implementation of
accelerator, brakes etc in the car.

Public members are explicitly visible ( enforce data abstraction )

Message Passing
Objects communicate with one another by sending and receiving information to each
other.
A message for an object is a request for execution of a procedure and therefore will
invoke a function in the receiving object that generates the desired results
Message passing involves specifying the name of the object, the name of the function
and the information to be sent.

Member Initialisation List


List of members to be initialised is indicated with their constructor as a comma
separated list followed by a colon. For more info, view here

https://app.simplenote.com/p/lSLzHg 9/22
02/08/2020 OOP with C++ :

Example

class Point {
private:
int x;
int y;
public:
Point(int i = 0, int j = 0):x(i), y(j) {} // initialisation using member ini
};

Used in 5 situations :-
Initialisation of non-static const data members
Initialisation of references
initialising member objects which don't have a default constructor
initialisation of base class members

When constructor's parameter name is same as data member of class. (this keyword
can also be used in this case, although)

It is better to use initialiser list for initialisation instead of assigning values in function
body due to performance reasons as it directly uses the copy constructor instead of
calling both the default constructor and the assignment operation. Destructor will be
called in each case, though.

"this" pointer
The compiler supplies an implicit pointer to every non-static member function of a
class, when it is called, this us called 'this' pointer. For more info, view here

this points to the calling object

this pointer is only an r-value, so its value can't be changed.

an object can be deleted (only if memory to it is dynamically allocated using new) by


using following syntax :-

delete this;

Situations when this pointer is used :-


When local variable's name is same as member name
To return reference to the calling object (Using *this )

Chaining of function calls (if it returns a reference to the object) Eg.


Obj.fun1().fun2().fun3() ;

https://app.simplenote.com/p/lSLzHg 10/22
02/08/2020 OOP with C++ :

Type of this pointer depends on function declaration. If member function of class X is


declared const, its type is const X *

Inheritance
The capability of a class to derive properties and characteristics from another class is
called Inheritance
Sub Class / Derived Class: The class that inherits properties from another class is called
Sub class or Derived Class.
Super Class / Base Class: The class whose properties are inherited by sub class is called
Base Class or Super class.
Syntax :

class subclass_name : access_mode base_class_name


{
//body of subclass
};

Various visibility modes :

Types of inheritance

1. Single Inheritance

https://app.simplenote.com/p/lSLzHg 11/22
02/08/2020 OOP with C++ :

2. Multilevel Inheritance :

3. Hierarchical Inheritance :

4. Multiple Inheritance :

5. Hybrid inheritance :

https://app.simplenote.com/p/lSLzHg 12/22
02/08/2020 OOP with C++ :

Dreaded Diamond Problem

The diamond problem occurs when two super-classes of a class have a common base
class ( multi-path inheritance ). For example, in the following diagram, the TA class gets
two copies of all attributes of Person class, this causes ambiguities.

It can be resolved using any of the 2 methods :

1. Use scope resolution operator to avoid ambiguity, but still there are 2 copies
2. Use virtual base class so that there is only a single copy

Storage Classes
5 Storage classes are there in C++

1. Automatic

https://app.simplenote.com/p/lSLzHg 13/22
02/08/2020 OOP with C++ :

Default storage class for local variables

2. Extern

Default storage class for global variables

3. Static

A static member is shared by all objects of the class

4. Register

For storing a variable in CPU registers instead of RAM, for faster access

5. Mutable

Used when we want to change only a specific property or data member of a


const object of a class

A function can have only 2 storage classes :

1. extern
2. static.

Out of these, static is possible only in member function of a class

Function Overriding
It is the redefinition of base class function in its derived class with same signature i.e
return type and parameters. Example -

class A {
public:
void display() {
cout<<"Base class";
}
};

class B:public A {
public:
void display() {
cout<<"Derived Class";
}
};

int main() {
B obj;
obj.display(); // Output : "Derived Class"

https://app.simplenote.com/p/lSLzHg 14/22
02/08/2020 OOP with C++ :

return 0;
}

Virtual Functions (Runtime Polymorphism)

Pure virtual functions

A pure virtual function is declared in base class as virtual func() = 0;

It makes the base class, an abstract class. Abstract classes can't be instantiated i.e. we
can't create objects of abstract classes but new classes can be derived using abstract
classes.

Whenever a pure virtual function is present in a base class, it should be overridden in


all the derived classes which should be concrete classes (have objects). If we don't do
this in a derived class, it becomes an abstract class

Mechanism of virtual functions

Compiler silently adds a void pointer to an object of a class which contains Virtual
functions

To accomplish late binding, the compiler creates a table called VTABLE for each class
that contains Virtual functions and for the classes derived from it. The compiler places
the addresses of virtual functions for that particular class in VTABLE .

If we don't redefine the function, it uses the address of the base class version in the
derived class

When objects of the base class or derived class are created it secretly places a pointer,
called the vpointer (VPTR) , which points to the VTABLE if its class.

When a function call is made through a base class pointer, the compiler inserts the
code to fetch the VPTR and lookup function address in the VTABLE, thus calling the
right function and causing Late Binding

VPTR must be initialised to point to the starting address of appropriate VTABLE (in
constructor)

Constructors and destructors in inheritance

When an object of derived class is created, all the base class constructors are always
called first, in constructor of derived class.(the reason is that only base class has access
to its members, not the derived class. Moreover, base class members need to be
initialised first as derived class members depend on base class)

https://app.simplenote.com/p/lSLzHg 15/22
02/08/2020 OOP with C++ :

Compiler calls the default constructor of base class if we don't explicitly call it in
constructor of derived class.

Constructors and destructors in dynamic binding

When a virtual function is called within a constructor or destructor , always the


member function of current class gets called (early binding) . In other words, virtual
mechanism doesn't work inside a constructor or a destructor

Destructor can be virtual but a constructor can't be. Because once an object has been
constructed, its VPTR is initialised, so the virtual function calls can take place

Dynamic type checking

When type checking occurs at runtime (not at compile time), it is called Dynamic type
checking .

It occurs through RTTI (runtime time information ) mechanism in C++

Used in dynamic casting of pointers

Eg.

Base *b = new Derived;

Object Slicing
A derived class object can be assigned to a base class object (called Object Slicing) but
the other way is not possible.

This is done at the cost of slicing of the additional data members of the derived class

Hence, we can call only functions of base class of a sliced object

It can be prevented by using pointers to class objects or by making the functions of base
class as pure virtual (abstract class) as it will give compile error if you create a base
class object

For example, view here

Size of a class object


Actually an object contains only the data members. Methods do not belong to any
specific object. They belong to the class. All objects share one copy of methods . When

https://app.simplenote.com/p/lSLzHg 16/22
02/08/2020 OOP with C++ :

you use “sizeof” operator on a class or an object you will only get the total size of the
data members.

Private members of a class are not inherited to a child class i.e. can't be used by
member functions of child class but remember that they are included while calculating
size of an object of child class

Size of an empty class is not 0. It is 1 byte generally, to ensure that 2 different objects
will have different addresses

If a class is derived from a virtual base class, it has a pointer to that virtual base class,
even when it is empty, resulting in a a size of at least 8 bytes always

Data conversion
From class to fundamental data type - Use operator overloading

Eg.

class radius
{
int num;

public:
void operator float () const {
float f = 3.14 x num;
return f;
}
};

From fundamental to class - Use conversion constructor (parametrised constructor)

We can prevent this type conversions most of the times, by using the keyword explicit
before the constructor. Know more here

Friend classes and friend functions

Friend classes

A friend class can access private and protected members of other class in which it is
declared as friend. It is sometimes useful to allow a particular class to access private
members of other class.

Example :

https://app.simplenote.com/p/lSLzHg 17/22
02/08/2020 OOP with C++ :

class Node {
private:
int key;
Node* next;
friend class LinkedList;
// Now class LinkedList can
// access private members of Node
};

Friend functions

Like friend class, a friend function can be given special grant to access private and
protected members.

A friend function can be any of :

i. A method of another class

ii. A global function

It can be used in 2 situations :-

i. Operator overloading

ii. If some particular data and functions are required to be shared between 2 or more
classes

Drawback of friend function is that it prevents the feature of data hiding upto some
extent

Know more here

Nested classes
A nested class is a class which is declared in another enclosing class. A nested class is a
member and as such has the same access rights as any other member. The members of
an enclosing class have no special access to members of a nested class, the usual access
rules shall be obeyed.

Factory methods
A factory method is a method which uses dynamic memory allocation to clone itself and
return a pointer to the new copy . Suppose you have a abstract class Shape and a series of
derived concrete classes such as Circle, Square, Rectangle, etc. A factory method of Circle
looks like

https://app.simplenote.com/p/lSLzHg 18/22
02/08/2020 OOP with C++ :

Shape * clone()
{
return new Circle(*this); // calling copy constructor
}

Copy constructor can not be used to clone objects in case of polymorphism. This is true
in both C++ and Java, because copy constructor does not support polymorphism .
Suppose you have a method which receives a concrete-class object with a Shape handle
and do something on it. Now if you want to make a copy of it in that method, with a
factory method you can say

public void modifyAndDisplay(Shape * obj)


{
Shape obj1 = obj. clone();
...
}

If the passed argument is a Circle, the Shape pointer “obj” will get a Circle, if it’s Square,
you will get a Square.

Templates
Templates are powerful features of C++ which allows you to write generic programs. In
simple terms, you can create a single function or a class to work with different data
types using templates.

2 types :

i. Function Template

ii. Class Template

Each instantiation of function template has its own copy of local static variables. View
more here

Function Template

A function template starts with the keyword template followed by template


parameter/s inside < > which is followed by function declaration. Syntax -

template <class T>


T someFunction(T arg)
{

https://app.simplenote.com/p/lSLzHg 19/22
02/08/2020 OOP with C++ :

... .. ...
}

You can also use keyword typename instead of class in the above example
When, an argument of a data type is passed to someFunction( ), compiler generates a
new version of someFunction() for the given data type.

Class Template

Syntax :

template <class T>


class className
{
... .. ...
public:
T var;
T someOperation(T arg);
... .. ...
};

className<dataType> classObject; // creation of object of a particular data type

Template specialisation

We can also specialise template to work differently, for a particular data type. Example-

// A generic sort function


template <class T>
void sort(T arr[], int size)
{
}

// A specialized version for char data type


template <>
void sort<char>(char arr[], int size)
{
// code to implement counting sort
}

Passing non-type parameters to templates

Non-type parameters must be const . The compiler must know the value of non-type
parameters at compile time.
It is generally used for specifying max or min values or any other constant value for a
particular instance of a template.

https://app.simplenote.com/p/lSLzHg 20/22
02/08/2020 OOP with C++ :

Exception Handling
Exceptions are run-time anomalies or abnormal conditions that a program encounters
during its execution.
View more here

Some points to remember


1. Extraction operator ( cin >> ) ignores whitespaces like '\n', ' ', '\t', etc. So, while taking
input with whitespaces , better use getline(cin,str)

2. If in a block a local variable of the same name as the global variable is declared, the
local variable will suppress the global one from the declaration line onwards. So, to
access the global variable from this block, use unary scope resolution operator "::" in
front of the identifier. For more uses of scope resolution operator, view here

3. Scope resolution operator (::) is also used, for ambiguity resolution. Ambiguity can be
occurred in using the multiple inheritance when a function with the same name occurs
in more than one base class.

4. Labels are identifiers followed by a colon, eg., the case label “case 3: ” in “switch”
structure. Labels are used in “switch” structure or “goto” statement to mark the
location of a statement. A label (and only a label) declared inside a function is in scope
everywhere in that function , in all nested blocks, before and after its own declaration.

5. Because block is the smallest unit in C++ , most variables/identifiers are of block scope .
They are local variables declared in a block.

6. The principle of least privilege (PLP) is the idea that at any user, program, or process
should have only the bare minimum privileges necessary to perform its function. In
most cases it is achieved by using of qualifier const, or the private or protected access
specifiers

7. By default, elements of an array are initialised to 0.

8. By default, arrays are passed by reference, similar to C , because name of an array is a


constant pointer pointing to its first element (except when used with sizeof operator
and & operator) .

9. A class can contain a static object of self type or a pointer to self type only. It can't have
an object of own type as a data member.

10. Const keyword

To put "const" qualifier in front of a parameter in both the function prototype and
function definition is to tell the compiler that the function doesn't modify the variable.

Eg.

https://app.simplenote.com/p/lSLzHg 21/22
02/08/2020 OOP with C++ :

void strcpy(char *, const char *);

A constant variable or pointer should be initialized when declared.

Eg.

const int size=4;

Published with Simplenote

https://app.simplenote.com/p/lSLzHg 22/22

You might also like