Ref. Notes - Unit 1
Ref. Notes - Unit 1
with C++
Unit 1
Introduction to object oriented approach
C++ What is OOP?
OOP stands for Object-Oriented Programming.
OOP helps to keep the C++ code DRY "Don't Repeat Yourself", and makes the code
easier to maintain, modify and debug
OOP makes it possible to create full reusable applications with less code and shorter
development time
Tip: The "Don't Repeat Yourself" (DRY) principle is about reducing the repetition of
code. You should extract out the codes that are common for the application, and place them at
a single place and reuse them instead of repeating it.
The prime purpose of C++ programming was to add object orientation to the C
programming language, which is in itself one of the most powerful programming languages.
The core of the pure object-oriented programming is to create an object, in code, that
has certain properties and methods. While designing C++ modules, we try to see whole
world in the form of objects. For example a car is an object which has certain properties
such as color, number of doors, and the like. It also has certain methods such as accelerate,
brake, and so on.
referred as OOP), programs were written in procedural language, they were nothing but a
long list of instructions. On the other hand, the OOP is all about creating objects that can
interact with each other, this makes it easier to develop programs in OOP as we can
understand the relationship between them.
3) OOP provides a good framework for code libraries where supplied software
components can be easily adapted and modified by the programmer.
4)Code Resusablity
Everything in C++ is associated with classes and objects, along with its attributes and
methods. For example: in real life, a car is an object. The car has attributes, such as weight
and color, and methods, such as drive and brake.
Attributes and methods are basically variables and functions that belongs to the class.
These are often referred to as "class members".
A class is a user-defined data type that we can use in our program, and it works as an
object constructor, or a "blueprint" for creating objects.
A class is like a blueprint of data member and functions and object is an instance of
class. For example, lets say we have a class Car which has data members (variables) such as
speed, weight, price and functions such as gearChange(), slowDown(), brake() etc. Now lets
say I create a object of this class named FordFigo which uses these data members and
functions and give them its own values. Similarly we can create as many objects as we want
using the blueprint(class).
Example
public:
//Functions
void brake(){
}
void slowDown(){
}
};
int main()
{
//ford is an object
Car ford;
}
Create an Object
In C++, an object is created from a class. We have already created the class
named MyClass, so now we can use this to create objects.
To create an object of MyClass, specify the class name, followed by the object name.
To access the class attributes (myNum and myString), use the dot syntax (.) on the
object:
int main() {
MyClass myObj; // Create an object of MyClass
Multiple Objects
Example
// Create a Car class with some attributes
class Car {
public:
string brand;
string model;
int year;
};
int main() {
Let's see an example of class that has two fields: id and name. It creates instance of
the class, initializes the object and prints the object value.
1. #include <iostream>
2. using namespace std;
3. class Student {
4. public:
5. int id;//data member (also instance variable)
6. string name;//data member (also instance variable)
7. };
8. int main () {
9. Student s1; //creating an object of Student
10. s1.id = 201;
11. s1.name = "Sonoo Jaiswal";
12. cout<<s1.id<<endl;
13. cout<<s1.name<<endl;
14. return 0;
15. }
Output:
201
Sonoo Jaiswal
Let's see another example of C++ class where we are initializing and displaying object
through method.
1. #include <iostream>
2. using namespace std;
3. class Student {
4. public:
5. int id;//data member (also instance variable)
6. string name;//data member(also instance variable)
7. void insert(int i, string n)
8. {
9. id = i;
10. name = n;
11. }
12. void display()
13. {
14. cout<<id<<" "<<name<<endl;
15. }
16. };
17. int main(void) {
18. Student s1; //creating an object of Student
19. Student s2; //creating an object of Student
20. s1.insert(201, "Sonoo");
21. s2.insert(202, "Nakul");
22. s1.display();
23. s2.display();
24. return 0;
25. }
Output:
201 Sonoo
202 Nakul
Let's see another example of C++ class where we are storing and displaying employee
information using method.
1. #include <iostream>
2. using namespace std;
3. class Employee {
4. public:
5. int id;//data member (also instance variable)
6. string name;//data member(also instance variable)
7. float salary;
8. void insert(int i, string n, float s)
9. {
10. id = i;
11. name = n;
12. salary = s;
13. }
14. void display()
15. {
16. cout<<id<<" "<<name<<" "<<salary<<endl;
17. }
18. };
19. int main(void) {
20. Employee e1; //creating an object of Employee
21. Employee e2; //creating an object of Employee
22. e1.insert(201, "Sonoo",990000);
23. e2.insert(202, "Nakul", 29000);
24. e1.display();
25. e2.display();
26. return 0;
27. }
Output:
In the following example, we define a function inside the class, and we name it "myMethod".
Note: You access methods just like you access attributes; by creating an object of the class
and using the dot syntax (.):
Inside Example
class MyClass { // The class
public: // Access specifier
void myMethod() { // Method/function defined inside the class
cout << "Hello World!";
}
};
int main() {
MyClass myObj; // Create an object of MyClass
myObj.myMethod(); // Call the method
return 0;
}
To define a function outside the class definition, you have to declare it inside the class
and then define it outside of the class. This is done by specifiying the name of the class,
followed the scope resolution :: operator, followed by the name of the function:
Outside Example
class MyClass { // The class
public: // Access specifier
void myMethod(); // Method/function declaration
};
int main() {
MyClass myObj; // Create an object of MyClass
myObj.myMethod(); // Call the method
return 0;
}
class Car {
public:
int speed(int maxSpeed);
};
int main() {
Car myObj; // Create an object of Car
cout << myObj.speed(200); // Call the method with an argument
return 0;
}
Access Specifiers
By now, you are quite familiar with the public keyword that appears in all of our class
examples:
Example
class MyClass { // The class
public: // Access specifier
// class members goes here
};
The public keyword is an access specifier. Access specifiers define how the members
(attributes and methods) of a class can be accessed. In the example above, the members
are public - which means that they can be accessed and modified from outside the code.
However, what if we want members to be private and hidden from the outside world?
private - members cannot be accessed (or viewed) from outside the class
protected - members cannot be accessed from outside the class, however, they can be
accessed in inherited classes. You will learn more about Inheritance later.
Example
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 (public)
myObj.y = 50; // Not allowed (private)
return 0;
}
error: y is private
Note: It is possible to access private members of a class using a public method inside the
same class. See the next chapter (Encapsulation) on how to do this.
Tip: It is considered good practice to declare your class attributes as private (as often as you
can). This will reduce the possibility of yourself (or others) to mess up the code. This is also
the main ingredient of the Encapsulation concept, which you will learn more about in the next
chapter.
Note: By default, all members of a class are private if you don't specify an access specifier:
Example
class MyClass {
int x; // Private attribute
int y; // Private attribute
};
Encapsulation
Encapsulation is a process of combining data and function into a single unit like
capsule. This is to avoid the access of private data members from outside the class. To
achieve encapsulation, we make all data members of class private and create public functions,
using them we can get the values from these data members or set the value to these data
members.
The meaning of Encapsulation, is to make sure that "sensitive" data is hidden from
users. To achieve this, you must declare class variables/attributes as private (cannot be
accessed from outside the class). If you want others to read or modify the value of a private
member, you can provide public get and set methods.
Example
#include <iostream>
using namespace std;
class Employee {
private:
// Private attribute
int salary;
public:
// Setter
void setSalary(int s) {
salary = s;
}
// Getter
int getSalary() {
return salary;
}
};
int main() {
Employee myObj;
myObj.setSalary(50000);
cout << myObj.getSalary();
return 0;
}
Example explained
The salary attribute is private, which have restricted access.
The public getSalary() method returns the value of the private salary attribute.
Inside main(), we create an object of the Employee class. Now we can use
the setSalary() method to set the value of the private attribute to 50000. Then we call
the getSalary() method on the object to return the value.
Why Encapsulation?
It is considered good practice to declare your class attributes as private (as often as
you can). Encapsulation ensures better control of your data, because you (or others)
can change one part of the code without affecting other parts
Abstraction is a process of hiding irrelevant details from user. For example, When
you send an sms you just type the message, select the contact and click send, the phone
shows you that the message has been sent, what actually happens in background when you
click send is hidden from you as it is not relevant to you.
o Data Abstraction is a process of providing only the essential details to the outside
world and hiding the internal details, i.e., representing only the essential details in the
program.
o Let's take a real life example of AC, which can be turned ON or OFF, change the
temperature, change the mode, and other external components such as fan, swing.
But, we don't know the internal details of the AC, i.e., how it works internally. Thus,
we can say that AC seperates the implementation details from the external interface.
o C++ provides a great level of abstraction. For example, pow() function is used to
calculate the power of a number without knowing the algorithm the function follows.
In C++ program if we implement class with private and public members then it is an example
of data abstraction.
o Private specifier: When the members are declared as private, members can only be
accessed only by the member functions of the class.
Let's see a simple example of abstraction in header files.
// program to calculate the power of a number.
1. #include <iostream>
2. #include<math.h>
3. using namespace std;
4. int main()
5. {
6. int n = 4;
7. int power = 3;
8. int result = pow(n,power); // pow(n,power) is the power function
9. std::cout << "Cube of n is : " <<result<< std::endl;
10. return 0;
11. }
Output:
Cube of n is : 64
In the above example, pow() function is used to calculate 4 raised to the power 3. The
pow() function is present in the math.h header file in which all the implementation details of
the pow() function is hidden.
Let's see a simple example of data abstraction using classes.
1. #include <iostream>
2. using namespace std;
3. class Sum
4. {
5. private: int x, y, z; // private variables
6. public:
7. void add()
8. {
9. cout<<"Enter two numbers: ";
10. cin>>x>>y;
11. z= x+y;
12. cout<<"Sum of two number is: "<<z<<endl;
13. }
14. };
15. int main()
16. {
17. Sum sm;
18. sm.add();
19. return 0;
20. }
Output:
Enter two numbers:
3
6
Sum of two number is: 9
In the above example, abstraction is achieved using classes. A class 'Sum' contains the
private members x, y and z are only accessible by the member functions of the class.
Advantages Of Abstraction:
o Implementation details of the class are protected from the inadvertent user level
errors.
o A programmer does not need to write the low level code.
o Data Abstraction avoids the code duplication, i.e., programmer does not have to
undergo the same tasks every time to perform the similar operation.
o The main aim of the data abstraction is to reuse the code and the proper partitioning of
the code across the classes.
o Internal implementation can be changed without affecting the user level code.
Polymorphism
11. {
12. int b;
13. public:
14. void display()
15. {
16. cout<<"Class B";
17. }
18. };
In the above case, the prototype of display() function is the same in both the base
and derived class. Therefore, the static binding cannot be applied. It would be great if the
appropriate function is selected at the run time. This is known as run time
polymorphism.
o Run time polymorphism: Run time polymorphism is achieved when the object's
method is invoked at the run time instead of compile time. It is achieved by method
overriding which is also known as dynamic binding or late binding.
The function to be invoked is known at the The function to be invoked is known at the run
compile time. time.
It is also known as overloading, early binding It is also known as overriding, Dynamic binding
and static binding. and late binding.
It provides fast execution as it is known at the It provides slow execution as it is known at the
compile time. run time.
It is less flexible as mainly all the things execute It is more flexible as all the things execute at the
at the compile time. run time.
C++ Inheritance
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.
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.
Single inheritance
Multiple inheritance
Hierarchical inheritance
Multilevel inheritance
Hybrid inheritance
Derived Classes
A Derived class is defined as the class derived from the base class.
Where,
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.
When the base class is privately inherited by the derived class, public members of
the base class becomes the private members of the derived class. Therefore, the
public members of the base class are not accessible by the objects of the derived
class only by the member functions of the derived class.
When the base class is publicly inherited by the derived class, public members of
the base class also become the public members of the derived class. Therefore, the
public members of the base class are accessible by the objects of the derived class
as well as by the member functions of the base class.
Note:
In C++, the default mode of visibility is private.
The private members of the base class are never inherited.
Where 'A' is the base class, and 'B' is the derived class.
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.
1. #include <iostream>
2. using namespace std;
3. class Account {
4. public:
5. float salary = 60000;
6. };
7. class Programmer: public Account {
8. public:
9. float bonus = 5000;
10. };
11. int main(void) {
12. Programmer p1;
13. cout<<"Salary: "<<p1.salary<<endl;
Output:
Salary: 60000
Bonus: 5000
In the above example, Employee is the base class and Programmer is the derived class.
Let's see another example of inheritance in C++ which inherits methods only.
1. #include <iostream>
2. using namespace std;
3. class Animal {
4. public:
5. void eat() {
6. cout<<"Eating..."<<endl;
7. }
8. };
9. class Dog: public Animal
10. {
11. public:
12. void bark(){
13. cout<<"Barking...";
14. }
15. };
16. int main(void) {
17. Dog d1;
18. d1.eat();
19. d1.bark();
20. return 0;
21. }
Output:
Eating...
Barking...
1. #include <iostream>
2. using namespace std;
3. class A
4. {
5. int a = 4;
6. int b = 5;
7. public:
8. int mul()
9. {
10. int c = a*b;
11. return c;
12. }
13. };
14.
15. class B : private A
16. {
17. public:
18. void display()
19. {
20. int result = mul();
21. std::cout <<"Multiplication of a and b is : "<<result<< std::endl;
22. }
23. };
24. int main()
25. {
26. B b;
27. b.display();
28.
29. return 0;
30. }
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.
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.
o Public: When the member is declared as public, it is accessible to all the functions of
the program.
o Private: When the member is declared as private, it is accessible within the class
only.
o Protected: When the member is declared as protected, it is accessible within its own
class as well as the class immediately derived from it.
A class consists of its objects, and also it may inherit from other classes.
It shows the attributes, classes, functions, and relationships to give an overview of the
software system.
relationship.
In the following example, Student_Name is dependent on the Student_Id.
Inline Function
C++ inline function is powerful concept that is commonly used with classes. If a
function is inline, the compiler places a copy of the code of that function at each point where
the function is called at compile time.
Any change to an inline function could require all clients of the function to be
recompiled because compiler would need to replace all the code once again otherwise it will
continue with old functionality.
To inline a function, place the keyword inline before the function name and define
the function before any calls are made to the function. The compiler can ignore the inline
qualifier in case defined function is more than a line.
Following is an example, which makes use of inline function to return max of two
numbers −
#include <iostream>
return 0;
}
When the above code is compiled and executed, it produces the following result −
Max (20,10): 20
Max (0,200): 200
Max (100,1010): 1010
Following is a simple C++ example to demonstrate the use of default arguments. We don’t
have to write 3 sum functions, only one function works by using default values for 3rd and
4th arguments.
#include<iostream>
using namespace std;
Output:
25
50
80
When Function overloading is done along with default values. Then we need to
make sure it will not be ambiguous.
The compiler will throw error if ambiguous. Following is the modified version of
above program.
#include<iostream>
using namespace std;
}
Error:
prog.cpp: In function 'int main()':
prog.cpp:17:20: error: call of overloaded
'sum(int, int)' is ambiguous
cout << sum(10, 15) << endl;
^
prog.cpp:6:5: note: candidate:
int sum(int, int, int, int)
int sum(int x, int y, int z=0, int w=0)
^
prog.cpp:10:5: note: candidate:
int sum(int, int, float, float)
int sum(int x, int y, float z=0, float w=0)
^
Key Points:
Default arguments are different from constant arguments as constant arguments can't be
changed whereas default arguments can be overwritten if required.
Default arguments are overwritten when calling function provides values for them. For
example, calling of function sum(10, 15, 25, 30) overwrites the value of z and w to 25
and 30 respectively.
During calling of function, arguments from calling function to called function are
copied from left to right. Therefore, sum(10, 15, 25) will assign 10, 15 and 25 to x, y,
and z. Therefore, the default value is used for w only.
Once default value is used for an argument in function definition, all subsequent
arguments to it must have default value. It can also be stated as default arguments are
assigned from right to left. For example, the following function definition is invalid as
subsequent argument of default variable z is not default.
#include <iostream>
using namespace std;
int main() {
int count = 5;
return 0;
}
Output
1. display() is called without passing any arguments. In this case, display() uses both the default
parameters c = '*' and n = 1.
2. display('#') is called with only one argument. In this case, the first becomes '#'. The second
default parameter n = 1 is retained.
3. display('#', count) is called with both arguments. In this case, default arguments are not used.
We can also define the default parameters in the function definition itself. The program
below is equivalent to the one above.
#include <iostream>
using namespace std;
int main() {
int count = 5;
return 0;
}
Things to Remember
1. Once we provide a default value for a parameter, all subsequent parameters must also have
default values. For example,
2. // Invalid
3. void add(int a, int b = 3, int c, int d);
4.
5. // Invalid
6. void add(int a, int b = 3, int c, int d = 4);
7.
8. // Valid
9. If we are defining the default arguments in the function definition instead of the function
prototype, then the function must be defined before the function call.
Consider a situation in which you have to check prime number. This problem is
solved below by making user-defined function in 4 different ways as mentioned above.
# include <iostream>
using namespace std;
void prime();
int main()
{
if (flag == 1)
{
cout << num << " is not a prime number.";
}
else
{
cout << num << " is a prime number.";
}
}
In the above program, prime() is called from the main() with no arguments.
prime() takes the positive number from the user and checks whether the number is a prime
number or not.
Since, return type of prime() is void, no value is returned from the function.
#include <iostream>
int prime();
int main()
{
int num, i, flag = 0;
if (flag == 1)
{
cout<<num<<" is not a prime number.";
}
else
{
cout<<num<<" is a prime number.";
}
return 0;
}
return n;
}
In the above program, prime() function is called from the main() with no arguments.
prime() takes a positive integer from the user. Since, return type of the function is an int, it
returns the inputted number from the user back to the calling main() function.
Then, whether the number is prime or not is checked in the main() itself and printed
onto the screen.
#include <iostream>
using namespace std;
int main()
{
int num;
cout << "Enter a positive integer to check: ";
cin >> num;
// There is no return value to calling function. Hence, return type of function is void. */
void prime(int n)
{
int i, flag = 0;
for (i = 2; i <= n/2; ++i)
{
if (n%i == 0)
{
flag = 1;
break;
}
}
if (flag == 1)
{
cout << n << " is not a prime number.";
}
else {
cout << n << " is a prime number.";
}
}
In the above program, positive number is first asked from the user which is stored in
the variable num.
Then, num is passed to the prime() function where, whether the number is prime or
not is checked and printed.
Since, the return type of prime() is a void, no value is returned from the function.
#include <iostream>
using namespace std;
int main()
{
int num, flag = 0;
cout << "Enter positive integer to check: ";
cin >> num;
if(flag == 1)
cout << num << " is not a prime number.";
else
cout<< num << " is a prime number.";
return 0;
}
return 0;
}
In the above program, a positive integer is asked from the user and stored in the
variable num.
Then, num is passed to the function prime() where, whether the number is prime or
not is checked.
Since, the return type of prime() is an int, 1 or 0 is returned to the main() calling
function. If the number is a prime number, 1 is returned. If not, 0 is returned.
Back in the main() function, the returned 1 or 0 is stored in the variable flag, and the
corresponding text is printed onto the screen.
Exception Handling
C++ Exceptions
When executing C++ code, different errors can occur: coding errors made by the
programmer, errors due to wrong input, or other unforeseeable things.
When an error occurs, C++ will normally stop and generate an error message. The
technical term for this is: C++ will throw an exception (throw an error).
Exception handling in C++ consist of three keywords: try, throw and catch:
The try statement allows you to define a block of code to be tested for errors while it
is being executed.
The throw keyword throws an exception when a problem is detected, which lets us
create a custom error.
The catch statement allows you to define a block of code to be executed, if an error
occurs in the try block.
Example
try {
// Block of code to try
throw exception; // Throw an exception when a problem arise
}
catch () {
Example
try {
int age = 15;
if (age >= 18) {
cout << "Access granted - you are old enough.";
} else {
throw (age);
}
}
catch (int myNum) {
cout << "Access denied - You must be at least 18 years old.\n";
cout << "Age is: " << myNum;
}
Example explained
We use the try block to test some code: If the age variable is less than 18, we
will throw an exception, and handle it in our catch block.
In the catch block, we catch the error and do something about it. The catch statement
takes a parameter: in our example we use an int variable (myNum) (because we are
throwing an exception of int type in the try block (age)), to output the value of age.
If no error occurs (e.g. if age is 20 instead of 15, meaning it will be be greater than
18), the catch block is skipped:
Example
int age = 20;
You can also use the throw keyword to output a reference number, like a custom error
number/code for organizing purposes:
Example
try {
int age = 15;
Example
try {
int age = 15;
if (age >= 18) {
cout << "Access granted - you are old enough.";
} else {
throw 505;
}
}
catch (...) {
cout << "Access denied - You must be at least 18 years old.\n";
}
Pass by Reference:
In the examples from the previous programs, we used normal variables when we
passed parameters to a function. You can also pass a reference to the function. This can be
useful when you need to change the value of the arguments:
Example
void swapNums(int &x, int &y) {
int z = x;
x = y;
y = z;
}
int main() {
// Call the function, which will change the values of firstNum and secondNum
swapNums(firstNum, secondNum);
return 0;
}
Return by reference
In C++ Programming, not only can you pass values by reference to a function but you
can also return a value by reference.
To understand this feature, you should have the knowledge of:
Global variables
If a variable is defined outside all functions, then it is called a global variable.
The scope of a global variable is the whole program. This means, It can be used and
changed at any part of the program after its declaration.
Likewise, its life ends only when the program ends
#include <iostream>
using namespace std;
// Global variable
int num;
// Function declaration
int& test();
int main()
{
test() = 5;
cout << num;
return 0;
}
int& test()
{
return num;
}
Output
5
In program above, the return type of function test() is int&. Hence, this function
returns a reference of the variable num.
#include <iostream>
#include <ctime>
using namespace std;
double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0};
double& setValues( int i ) {
return vals[i]; // return a reference to the ith element
}
// main function to call above defined function.
int main () {
cout << "Value before change" << endl;
for ( int i = 0; i < 5; i++ ) {
cout << "vals[" << i << "] = ";
cout << vals[i] << endl;
}
setValues(1) = 20.23; // change 2nd element
setValues(3) = 70.8; // change 4th element
cout << "Value after change" << endl;
for ( int i = 0; i < 5; i++ ) {
cout << "vals[" << i << "] = ";
cout << vals[i] << endl;
}
return 0;
}
When the above code is compiled together and executed, it produces the following result
−
When returning a reference, be careful that the object being referred to does not
go out of scope. So it is not legal to return a reference to local var. But you can always
return a reference on a static variable.
int& func() {
int q;
//! return q; // Compile time error
static int x;
return x; // Safe, x lives outside this scope }
*
* *
* * *
* * * *
* * * * *
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
* * * * *
* * * *
* * *
* *
*
1 2 3 4 5
1 2 3 4
1 2 3
1 2
1
*
* * *
* * * * *
* * * * * * *
* * * * * * * * *
1
2 3 2
3 4 5 4 3
4 5 6 7 6 5 4
5 6 7 8 9 8 7 6 5
1
2 3
4 5 6
7 8 9 10