Object Oriented Programming using C++
Notes Compiled by Prof. Akshay Gaikwad
Index
UNIT |
Name of Chapter |
Page No. |
I |
Object Oriented Methodology Principles of OOP’s |
2 to 53 |
II |
Classes and Objects Member Functions Constructor and Destructor |
54 to 72 |
III |
Inheritance |
73 to 90 |
IV |
Polymorphism Virtual Function |
91 to 109 |
V |
File Operations |
110 to 116 |
History of Computer Programming Languages
1. Ever since the invention of Charles Babbage’s difference engine in 1822, computers have required a means of instructing them to perform a specific task.
2. This means is known as a programming language.
3. In the beginning, Charles Babbage’s difference engine was able to execute ‘physical motion’ tasks like calculations.
4. Eventually, physical motion was replaced by electrical signals when the US Government built the ENIAC in 1942.
5. In 1945, John Von Neumann introduced, “shared-program technique”.
6. In 1949, a few years after Von Neumann’s work, the language “Short Code” appeared.
7. It was the first computer language for electronic devices and it required the programmer to change its statements into 0’s and 1’s by hand.
8. In 1951, Grace Hopper wrote the first compiler. A compiler is a program that turns the language’s statements into 0’s and 1’s for the computer to understand.
9. This lead to faster programming, as the programmer no longer had to do the work by hand.
10. In 1957, the first of the major languages appeared in the form of FORTRAN. Its name stands for FORmula TRANslating system.
11. The language was designed at IBM for scientific computing.
12. Though FORTAN was good at handling numbers, it was not so good at handling input and output, which mattered most to business computing.
13. Business computing started to take off in 1959, and because of this, COBOL (Conference on Data Systems Languages) was developed. It was designed from the ground up as the language for businessmen (COMMERCIAL APPLICATIONS).
14. In 1997, 80% of business ran on COBOL.
15. In 1960s ALGOL 60 (short for ALGOrithmic Language 1960) was designed by Backus.
16. In 1963, CPL (Cambridge Plus London) was developed jointly between the Mathematical Laboratory at the University of Cambridge and the University of London.
17. In 1967, Martin Richards developed BCPL (Basic Combined Programming Language).
18. In 1970, B was developed by developed at Bell Labs. It is the work of Ken Thompson with Dennis Ritchie.
19. In 1972, C Language was developed by “Dennis MacAlistair Ritchie”.
Q.1 Discuss Procedure-Oriented Programming with its Advantages and Disadvantages?
Q. 2 Some Characteristics exhibited by procedure-oriented programming are:
• Emphasis is on doing things (algorithms).
• Large programs are divided into smaller programs known as functions.
• Most of the functions share global data.
• Data move openly around the system from function to function.
• Functions transform data from one form to another.
• Employs top-down approach in program design.
Advantages of Procedure Oriented Programming:
Disadvantages of Procedure Oriented Programming:
Q.4 What is Object Oriented Programming?
Q.5 Explain Advantages and Disadvantages of OOP’s?
Some of the advantages of object-oriented programming include:
1. Improved software-development productivity: Object-oriented programming is modular, as it provides separation of duties in object-based program development. It is also extensible, as objects can be extended to include new attributes and behaviours. Objects can also be reused within an across applications. Because of these three factors – modularity, extensibility, and reusability – object-oriented programming provides improved software-development productivity over traditional procedure-based programming techniques.
2. Improved software maintainability: For the reasons mentioned above, object oriented software is also easier to maintain. Since the design is modular, part of the system can be updated in case of issues without a need to make large-scale changes.
3. Faster development: Reuse enables faster development. Object-oriented programming languages come with rich libraries of objects, and code developed during projects is also reusable in future projects.
4. Lower cost of development: The reuse of software also lowers the cost of development. Typically, more effort is put into the object-oriented analysis and design, which lowers the overall cost of development.
5. Higher-quality software: Faster development of software and lower cost of development allows more time and resources to be used in the verification of the software. Although quality is dependent upon the experience of the teams, object oriented programming tends to result in higher-quality software.
Some of the disadvantages of object-oriented programming include:
1. Steep learning curve: The thought process involved in object-oriented programming may not be natural for some people, and it can take time to get used to it. It is complex to create programs based on interaction of objects. Some of the key programming techniques, such as inheritance and polymorphism, can be challenging to comprehend initially.
2. Larger program size: Object-oriented programs typically involve more lines of code than procedural programs.
3. Slower programs: Object-oriented programs are typically slower than procedure based programs, as they typically require more instructions to be executed.
4. Not suitable for all types of problems: There are problems that lend themselves well to functional-programming style, logic-programming style, or procedure-based programming style, and applying object-oriented programming in those situations will not result in efficient programs.
Q.6 Explain the features of object oriented programming? Or
Principles of Object Oriented Programming (OOP’s)
Q.7 Explain benefits of Object Oriented Programming?
Object Oriented Programming finds a lot of applications in real life business systems. The various places where object oriented programming is required:
Difference between Procedure Oriented Programming (POP) & Object Oriented Programming (OOP)
|
Procedure Oriented Programming |
Object Oriented Programming |
Divided Into |
In POP, program is divided into small parts called functions. |
In OOP, program is divided into parts called objects. |
Importance |
In POP, Importance is not given to data but to functions as well as sequence of actions to be done. |
In OOP, Importance is given to the data rather than procedures or functions because it works as a real world. |
Approach |
POP follows Top Down approach. |
OOP follows Bottom Up approach. |
Access Specifiers |
POP does not have any access specifier. |
OOP has access specifiers named Public, Private, Protected, etc. |
Data Moving |
In POP, Data can move freely from function to function in the system. |
In OOP, objects can move and communicate with each other through member functions. |
Expansion |
To add new data and function in POP is not so easy. |
OOP provides an easy way to add new data and function. |
Data Access |
In POP, Most function uses Global data for sharing that can be accessed freely from function to function in the system. |
In OOP, data can not move easily from function to function,it can be kept public or private so we can control the access of data. |
Data Hiding |
POP does not have any proper way for hiding data so it is less secure. |
OOP provides Data Hiding so provides more security. |
Overloading |
In POP, Overloading is not possible. |
In OOP, overloading is possible in the form of Function Overloading and Operator Overloading. |
Examples |
Example of POP are : C, VB, FORTRAN, Pascal. |
Example of OOP are : C++, JAVA, VB.NET, C#.NET. |
Q.8 Explain Basic concept of Object Oriented Programming?
Objects
Classes
Abstraction
Encapsulation
Inheritance
Polymorphism
Dynamic Binding
Message Passing
Overloading
Exception Handling
Objects are the basic unit of OOP. They are instances of class, which have data members and use various member functions to perform tasks. You can imagine it to be similar to variable of class like we have variable of structure.
class Sample // class declaration
{
private: // access specifier
int a;
int b; // data members
public:
void function(); // member function
};
int main()
{
Sample s1; // s1 is an object of class Sample
//----- code----
return 0;
}
It is similar to structures in C language. Class can also be defined as user defined data type but it also contains functions in it. So, class is basically a blueprint for object. It declares & defines what data variables the object will have and what operations can be performed on the class's object. For examples, Mango, Apple and orange members of class fruit.
Classes are user-defined that types and behave like the built-in types of a programming language. The syntax used to create an object is not different then the syntax used to create an integer object in C. If fruit has been defines as a class, then the statement
Fruit Mango;
Will create an object mango belonging to the class fruit.
Data Abstraction refers to showing only the essential features of the application and hiding the details. In C++, classes provide methods to the outside world to access & use the data variables, but the variables are hidden from direct access.
For example: if there is a class for circle we need to just define the radius of the object of this class. We need not bother about anything else of that object.
The data of an object is hidden from other objects. This is called encapsulation.
It can also be said data binding. Encapsulation is all about binding the data variables and functions together in class. Encapsulation is achieved by putting data and functions associated with it into a class. The advantage of data encapsulation is that the data is hidden from other functions and hence they cannot access it or change it directly. Thus unexpected changes in the data is not possible.
Inheritance is a way to reuse once written code again and again. The class which is inherited is called base calls & the class which inherits is called derived class. So when, a derived class inherits a base class, the derived class can use all the functions which are defined in base class, hence making code reusable.
Polymorphism makes the code more readable. It is a features, which lets is create functions with same name but different arguments, which will perform differently. That is function with same name, functioning in different
As you know, polymorphism is a technique of calling functions when needed b the objects of that class. This decision to call a function for that specific class is done t runtime. This is known as ‘Dynamic Binding’ or ‘Late Binding’
An object-oriented program consists of a set of objects that communicate with each other. The process of programming in an object-oriented language, involves the following basic steps:
1. Creating classes that define object and their behaviour,
2. Creating objects from class definitions, and
3. Establishing communication among objects.
Overloading is a part of polymorphism. Where a function or operator is made & defined many times, to perform different functions they are said to be overloaded.
Exception handling is a feature of OOP, to handle unresolved exceptions or errors produced at runtime.
Q.9 Explain Character Set in C++.
Character set is the combination of English language (Alphabets and White spaces) and math's symbols (Digits and Special symbols). Character Set means that the characters and symbols that a C++ Program can understand and accept. These are grouped to form the commands, expressions, words, c-statements and other tokens for C++ Language.
There are mainly four categories of the character set as shown in the Figure.
1. Alphabets
Alphabets are represented by A-Z or a-z. C- Language is case sensitive so it takes different meaning for small and upper case letters. By using this character set C statements and character constants can be written very easily. There are total 26 letters used in C-programming.
2. Digits
Digits are represented by 0-9 or by combination of these digits. By using the digits numeric constant can be written easily. Also numeric data can be assigned to the C-tokens. There are total 10 digits used in the C-programming.
3. Special Symbols
All the keyboard keys except alphabet, digits and white spaces are the special symbols. These are some punctuation marks and some special symbols used for special purpose.
There are total 30 special symbols used in the C-programming. Special symbols are used for C-statements like to create an arithmetic statement +, -, * etc. , to create relational statement <, >, <=, >=, == etc. , to create assignment statement =, to create logical statement &&, II etc. are required.
4. White Spaces
White spaces has blank space, new line return, Horizontal tab space, carriage ctrl, Form feed etc. are all used for special purpose. Also note that Turbo-C Compiler always ignore these white space characters in both high level and low level programming.
Q.10 Explain the Process of Compiling Source Code
compiler - produces an object file.
linker - turns object file into executable program.
LIBRARY = a collection of linkable files that were created, inherent in an OS or purchased.
FUNCTION = a block of code that performs a service, one or more actions (adding 2 numbers or printing to the screen).
CLASS = a collection of data and related functions.
DEBUG = edit source code, recompile, re-link and rerun
Q.11 Explain Syntax and Grammar in C++
1. # = This symbol triggers the preprocessor.
2. #include = Every time it sees the # sign it modifies and inserts the source code contained in the specified file in the <> brackets..
It is this code that is fed to the compiler, not the actual "#include" statement.
3. iostream.h = a common header file provided by most compilers in the standard library. It contains source code needed for basic
I/O (input/output) operations. Without specifying that source code from this file be included in the program, basic
functions like cout << and cin >> would not be defined or understood by the compiler.
4. int main() = a special function, starts automatically when program executed. Like all functions it must state what kind of value it
will return. It will always return int (an integer) or void. It is invoked by the operating system to start the program. All
calls to outside source will be contained in the main() function.
5. function - a block of code that performs one or more actions. It is invoked or called. Functions always begin with a { and end with a
}. Opening and closing parenthesis - ( and ), are used to pass parameters to the function from other parts of the
program. These parameters can be hard coded values, integers, variables, array elements or other functions. A function
must include a return type. While this will be expanded later, in the case of "main" function, the return type will always
either be "int" or "void".
6. cout = Used to output information to the display. It is contained in the included header file "iostream.h" that we added with the
preprocessor.
7. << = direction of data stream. It is "<<" for cout when outputting data to the display. It moves the opposite direction for user
input, becoming ">>", when using cin.
8. "Hello World\n"; = Whatever is placed in quotation marks is sent to the display.
9. \n = inserts a carriage return/end of line after displaying "Hello World".
10. ; = Terminates a statement, cout << "Hello World!\n"; is a statement that must be terminated with a semicolon.
11. return 0; = ends the main() function, thus ending the program.
Q.12 Explain simple C++ program
Let us begin with a simple example of a C++ program that prints a string on the screen.
Printing A String
#include<iostream> Using namespace std; int main()
{
cout<<” c++ is better than c \n”; return 0;
}
This simple program demonstrates several C++ features.
Program feature
Like C, the C++ program is a collection of function. The above example contain only one function main(). As usual execution begins at main(). Every C++ program must have a main(). C++ is a free form language. With a few exception, the compiler ignore carriage return and white spaces. Like C, the C++ statements terminate with semicolons.
Comments
C++ introduces a new comment symbol // (double slash). Comment start with a double slash symbol and terminate at the end of the line. A comment may start anywhere in the line, and whatever follows till the end of the line is ignored. Note that there is no closing symbol.
The double slash comment is basically a single line comment. Multiline comments can be written as follows:
The C comment symbols /*,*/ are still valid and are more suitable for multiline comments. The following comment is allowed:
/* This is an example of C++ program to illustrate some of its features
*/
C++ Tokens
A token is the smallest unit that can be processed by a c++ compiler. It can be categorized into different types namely:-
Q.13 Explain some keywords in C++?
Keywords (or reserved words):-
These are some special words that have a predefined meaning for the C++ compiles. Hence, these words cannot be used as identifiers.
These are a set of words which are reserved for the certain operations and hence are alspo sometimes referred as reserved words.
All keywords are in lowercase.
These are the words used for special purposes or predefined tasks. These words should be written in small letters or lowercase letters. Some of the keyword used in c++ are as follows:
These keywords include all those keywords also as declared by ANSI(American National Standard Institute) C. This institute has published the standards to be used in C Programming language.
Q.14 Explain Identifiers in C++?
Identifiers:- It is a name used to represent a variable constant, array name, function name, class, object etc. There are some rules while defining an identifiers:-
Q.15 Explain Constants in C++?
Constants:- A value which remain constant throughout the program execution is known as constant. An identifier can be declared as a constant as illustrated below:-
i) # define N 20
ii) # define PI 3.14
iii) const int M=35; or const m=35;
Note:- When the constant identifier is of type integer, then keyword int is optional. As a default the identifier is considered as integer. Only one value can be declared as constant at a time with the keyword const.
Q.16 Explain Variables in C++?
Variables:- An identifier whose value can be modified/ altered is known as a variable. A variable can be declared as shown below.
int a;
float x;
char ch;
Here a is a variable of type integer, x is a variable of type float, where as ch is a variable of type char. Values can be assigned with a, x & ch as shown below.
a=10; x=7.5; ch=’d’; a=a+5; x=x-4;
Q.17 Explain Literals in C++?
Literals:- The constant values used in c++ are known as literals, there are four type of literals namely.
i) Integer constant:- A value written without fraction part is known as integer constant. Example: 25, -674, 0 etc.
ii) Floating constant:- A value written with fraction part is floating value. Value of this type can be written with or without exponent form. Example: 2.34, -9.2154, 1.21E10
iii) Character constant:- A single character written within single quotation marks is known as character constant. Example: ‘g’, ‘9’, ‘$’ etc
iv) String constant:- It is an array of characters enclosed in double quotation marks. Example: “Shubham”, “03-aug-2009”. Double quotation mark is a delimiter which determines length of a string.
Q.18 Explain Data types in C++?
Data types:- In c++ a data type indicates what type of data and memory locations are required for storing that type of data in memory.
The data type can be grouped it no 3 types (Primitive, Derived and User defined).
Q.19 Explain Variable declaration and initialisation in C++?
Variable declaration and initialisation:- A variable to be used in a program should be declared with its proper datatype.
Suppose variable a is of type integer, b is of type float, c is of type character and d is of type long integer, then declaration can be carried out as listed below:-
int a;
float b;
long int d;
char c;
A variable can be initialised with pre determine value as shown below
int s=0;
char ch= ‘y’;
Operators:- C++ is rich in supporting many types of operators as illustrated below.
A statement is a command given to the system to carry out a specific task. The statement consists of operators and operands where operators specify type of operation to be carried on operand.
Example:
c=a+b;
Here a and b are identifiers whose value is to be added and assigned in c. ‘+’ and ‘=’ are operators.
Arithmatic operators:- These operators are used to carry out simple arithmetic operations such as addition, subtraction, multiplication, division etc.
+ addition
- subtraction
/ division
* multiplication
% remainders
Example: 14%5=4 14%(-5)=4 5%14=5 (-14)%5=-4
Thus the sign of the numerator determines the size of remainder.
a) Assignment operators:- The C++ uses symbol ‘=’ as an identifier.
Example: a=10;
const int b=5;
b) Unary operator:- This operator always preceeds a value. Tha symbol – is generally used as unary ‘-‘ as shown below.
x=-y;
a=a-(-b);
Increment and decrement operator:- The C++ facilitates use of two new operators ‘++’ and ‘--‘ . The ‘++’ operator increments value of a variable by 1 while – decrements the value of a variable by 1.
Example: ++a; a++; => a=a+1;
--a; a--; => a=a-1;
let a=6
i) x=++a; => x=7 and a=7
ii) x=a++; => x=6 and a=7
In i) the value of a is incremented by 1 i.e. a becomes 7 and then x is assigned with a new value which is known as preincrement and operator used is called as preincrement operator.
In ii) the value of a is assigned to x before incrementing a which is known as postincrement and operator used is called as postincrement operator.
Relational operator:- Operators of this type are used to compare two values for finding relation between the values. For instance:- to find maximum of two numbers we have to use <,> operators.
> greater than
< less than
>= greater than or equal to
<= less than or equal to
== to check equality
!= not equal to
In c++ the relational operator returns one when condition is true otherwise zero.
Logical operator:- These operators can be used to connect two or more relational expressions or to find zero or non zero value assigned with a variable. The C++ uses three logical operators.
&& Logical AND
|| Logical OR
! Logical NOT
The first two operators can always be used between two values or relations while the third always precedes a value or a relation. Logical operators treat non zero values as ‘1’ and zero values as ‘0’.
Conditional Operator:- It is also known as ternary operator. It uses symbols ‘?’ and ‘:’ to form an operator.
Syntax: condition ? statement1 : statement2;
big= a>b ? a : b;
If value of a is greater than b then big=a otherwise big=b.
Bitwise operator:- These operators can be used to perform operations on binary digits known as bits. They include
1. Bitwise AND(&):- This operator performs operation on two bits and provides bit ‘1’ as output if both the bits are high(1) otherwise ‘0’.
2. Bitwise OR(|):- This operator performs operation on two bits and provides bit ‘1’ as output when atleast one of the bits is high(1) otherwise ‘0’.
3. Bitwise Ex-OR(^):- This operator performs operation on two bits and provides bit ‘1’ as output when both the bits are distinct otherwise ‘0’.
4. Bitwise 1’s complement(~):- It performs operation on one bit and provides output ‘1’ for input ‘0’ and vice versa. This is also known as bitwise NOT operator.
5. Shift right operator(>>):- This operator shifts the binary bits of a number towards right and fills the leftmost blank position with ‘0’.
6. Shift left operator(>>):- This operator shifts the binary bits of a number towards left and fills the rightmost blank position with ‘0’.
Shorthand operators:- The arithematic and bitwise operators can be used as short hand operators as illustrated below.
a=a+b; => a+=b;
a=a-b; => a-=b;
a=a*b; => a*=b;
a=a^b; => a^=b;
Special operators:- The C++ supports a large number of special operators. Few of them are listed below.
I Coma(,):- It is used to separate a list of variable in variable declaration.
II. &:- It is known as address operator or reference operator. It is used to provide a duplicate name or to assign address to a new variable.
III. *:- This is used to declare a pointer variable of type int, float etc.
IV. sizeof():- This operator provides or display the size of a datatype in bytes.Remember sizeof() is not a function.
V. Casting operator:- It is used to convert one type of data into another type while executing a statement, temporarily.
int a=10,m=3;
a/m=3;
(float)a/m=3.333333;
a/(float)m=3.333333;
(float)(a)/m=3.333333;
VI. New:- This operator is used to allocate memory space or storage space for a pointer variable.
int *a;
a= new int[10];
VII. delete:- This operator is used to release memory space allocated to the pointer variable.
VIII. Scope resolution operator(::):- This operator plays vital role in OOPs while expanding or defining function of a class calling a static member function and also helps us to process a global variable in functions.
Q.20 Explain precedence and associativity of operators in C++?
The precedence of the operators means the sequence in which the operators will be operated on, in case of multiple operators in a statement i.e. which operator will be executed first and which operator will be executed later.
The associativity of operators refers to the direction in which the operation will be in case of equal precedence operators i.e. if multiple are there in a statement then it will be performed from left to right. We will see more about this in the examples followed by this section.
Q.21 Explain types of errors in C++ ?
Syntax error:- This error occurs due to following reason.
I. Not following the grammatical rules used in declaration of identifier.
II. Not declaring an identifier used in program.
III. Not terminating statement by semicolon.
IV. Not providing equal number of opening and closing braces etc.
These errors can be rectified by the user as it is displayed while compiling the program.
Logical error:- This error won’t be displayed on the screen. However it will lead to display wrong results. Example: An infinite loop. This error lead to abnormal termination of a program or infinite loop.
Runtime error:- This error occurs while running a program by displaying the message listed below.
I. Division by 0.
II. Overflow
III. Underflow
Q. 22 Explain the new operator in C++ and compare it with malloc()?
The new operator is used in C++ for allocating memory dynamically. In the C Programming language we used malloc() function for the same. The programs based on the new operator will be seen in further chapters. Difference between the new operator and malloc() function is as follows:
NEW OPERATOR |
MALLOC() Function |
It is an operator |
It is an function |
It returns the exact data type |
It returns the void type data which is to be typed casted to the required data type. |
It calls the constructor and can also be used to define the primitive data types |
It does not call the constructor. |
If else Statements in C++
if:- The statement following the if statement is executed when the condition given is true.
if(condition)
s1;
s2;
When the condition is true statement s1 and then s2 is executed. If the condition is false only s2 is executed. If we want to execute more than 1 statements when condition is true then we should write all those statements within braces {} after if.
if(condition)
{
s1;
s2;
}
s3;
when the condition is true statement s1, s2 and then s3 is executed. If the condition is false only s3 is executed.
example:-
c=0;
if(sales>=20000)
c=0.1*sales;
cout<< “commission = ”<<c;
if-else:- Also known as either or. This statement is used to select one statement and ignore the other statements.
if(condition)
s1;
else
s2;
when the condition is true statement s1 is executed. If the condition is false s2 is executed. Thus one of the statements, either s1 or s2 is always executed.
example:-
if(sales>=20000)
c=0.1*sales;
else
c=0;
cout<< “commission = ”<<c;
if-else-if-else:- It is a branching statement which can choose and execute on of the statements available depending upon the condition.
if(condition1)
s1;
else if(condition2)
s2;
else
s3;
when the condition1 is true statement s1 is executed and rest are ignored. When condition1 is false condition2 is verified. If condition2 is true statement s2 is executed and other statements are ignored and so on. Thus only one statement is executed from the top, depending upon the condition. The statement following else is executed when all the conditions are false. However else clause is optional.
example:-
if(sales>=20000)
c=0.1*sales;
else if(sales>=10000)
c=0.05*sales;
else
c=0;
cout<< “commission = ”<<c;
Lets have some examples
Write a program to check whether the given year is leap year or not.
#include<iostream>
void main()
{
int y;
cout<< “Enter the year”;
cin>>y;
if((y%4==0) && (y%100!=0 && y%400==0))
cout<< “It is a leap year”;
else
cout<< “It is not a leap year”;
}
Write a program to read three numbers and find the least among them.
#include<iostream>
void main()
{
int a,b,c,s;
cout<< “Enter three values”;
cin>>a>>b>>c;
if(a<b)
s=a;
else
s=b;
if(c<s)
s=c;
cout<< “The least value = ”<<s;
}
Write a program to display grades.
#include<iostream>
void main()
{
int m;
cout<< “Enter marks in computer science”;
cin>>m;
if(m>90)
cout<< “Distinction”;
else if(m>=75)
cout<< “Grade A”;
else if(m>60)
cout<< “Grade B”;
else if(m>50)
cout<< “Grade C”;
else
cout<< “Fail”;
}
Q. 23 Write a program to find whether the given positive integer is odd or even.
Q. 24 Write a program to check whether giver integer is divisible by 7, 15 and 22.
Q. 25 Write a program to read a, b and c of ax2+bx+c and display roots.
Q. 26 Write a program to read a character and check whether it is digit, alphabet or special character.
Switch statement in C++
switch:- It is a multi branch statement which can be used to select and execute one of the available statements.
switch(value)
{
case 1: statement 1; break;
case 2: statement 2; break;
case n: statement n; break;
default: statement d;
}
Where value can be a variable of type numeric or character. The case label 1 to n can also be written with constant identifiers.
When the value assigned matches with case label 1 statement 1 is executed. The break statement written after statement 1 transfers the control out of the switch statement. When the value doesn’t match with case label 1 then it checks with case label 2 and so on. When the value assigned doesn’t match with any of the case labels (1 to n) then the default clause is considered and the statement d is executed.
Default clause is optional like else clause in if-else-if-else statement.
example:
switch(c)
{
case1: cout<< “north”; break;
case2: cout<< “south”; break;
case3: cout<< “east”; break;
case4: cout<< “west”; break;
default: break;
}
Q. 27 Write a program to display the grades as listed below by using switch statement
80-100 Distinction
60-79 Grade A
40-59 Grade B
Otherwise fail
#include<iostream>
void main()
{
int m;
cout<< “Enter marks scored: ”;
cin>> m;
switch( m/10 ) //marks are divided by 10
{
case 10:
case 9:
case 8: cout << “Distinction\n”; break;
case 7:
case 6: cout << “Grade A\n”; break;
case 5:
case 4: cout << “Grade B\n”; break;
default: cout << “Fail\n”; break;
}
}
Q. 28 Write a program to design simple calculator by using switch statement to carry out addition, multiplication, division and subtraction.
Q. 29 Write a program to read a number from 1-7 and print day of week corresponding to that number using switch statement.
Looping in C++
while:- It is a repeated structure statement which repeats a statement given as long as the condition is true.
while(condition)
statement1;
statement1 is executed till the condition is true.
example:
int i = 1; //statement 1
while (i <= 20) //condition
{
cout<< i << “\t”;
++i; //statement 2
}
Output: 1 2 3......... 20
do while:- Like while statement it repeats a statement given as long as the condition is satisfied unlike in while statement the condition is checked at the end of the structure.
do
{
statement1;
}
while(condition);
statement1 is executed till the condition is true. Here while statement contains a semicolon.
example:
int i = 1; //statement1
do
{
cout<< i << “\t”;
++i; // statement 2
} while(i <= 20); //condition
Output: 1 2 3......... 20
for:- It is a repeated structure which can repeat a statement as long as the given condition is satisfied.
for(statement1; condition; statement2)
statement3;
where statement1 initialises control variable, condition is used to check whether statement written after loop can be repeated or not , statement2 is used to modify the control variable. Statement3 is a simple statement (having only one statement) or compound statement (a set of statements written within braces {} ) which can be repeated as long as condition is true or satisfied.
example:
for(i = 1; i <= 20; i++)
{
cout<< i << “\t”;
++i;
}
Output: 1 2 3......... 20
Nested loop:- When one repeated structure is written within one or more such repeated structures then the entire structure is known as nested loop.
example:
int i = 1;
while(i <= 3)
{
int j = 1;
while(j <= 2)
{
cout<< i << “;” << j << “ ”;
j++;
}
i++;
}
Output: 1;1 1;2 2;1 2;2 3;1 3;2
Q.30 Explain difference between while loop and do-while loop?
While Loop |
Do-While Loop |
While(condition) {
Statements;
}
|
{
Statements;
}while(condition); |
|
|
|
|
|
|
|
|
Lets have some examples.
Q. 31. Write a program to read two positive integers and check whether they are coprime or not.
#include<iostream>
void main()
{
int a, b, p, q;
cout<< “Enter two numbers”;
cin>> a >> b;
p = a;
q = b;
while (b != 0)
{
int r = a % b;
a = b;
b = r;
}
if(a == 1)
cout<< p << “ and ”<< q << “are coprime”;
else
cout<< p << “ and ”<< q << “are not coprime”;
}
Q. 32 Write a program to read a list of numbers terminated by -1 and determine positive average of positive numbers.
#include<iostream>
void main()
{
int a, s = 0, i = 0;
cout<< “Enter a list of numbers terminated by -1”;
do
{
cin>> a;
if(a < 0)
continue;
s = s + a;
++i;
}while(a != -1);
cout<< “No of +ve numbers read”<< i << endl << “Avg=”<< s/float(i);
}
Q. 33 Write a program to display odd factors of a positive integer.
#include<iostream>
#include<iomanip.h>
void main()
{
int a, n;
cout<< “Enter the value of a”;
cin>> a;
for(i = 1; i <= n; i += 2)
if(a % i == 0)
cout<<setw(5)<<i;
}
Q.34 Write a program to print following pattern.
54321
5432
543
54
5
#include<iostream>
#include<iomanip.h>
void main()
{
int i, j;
for (i = 1;i <= 5;i++)
{
for (j = 5; j >= i; j--)
cout<< setw(5) << j;
cout<< endl;
}
}
Q. 35 Write a program to display factorial of a given positive integer.
Q. 36 Write a program to read a positive integer and check whether it is prime or not.
Q. 37 Write a program to display binary equivalent of a given decimal no.
Q. 38 Write a program to find sum of the digits and reverse of an n digit number.
Q. 39 Write a program to display following pattern.
1
212
32123
4321234
543212345
Functions in C++
Q.40 Write a Short note on Function. Explain how to define, declare and call a Function.
A function is a group of statements that together perform a task. Every C++ program has at least one function, which is main(), and all the most trivial programs can define additional functions.
You can divide up your code into separate functions. How you divide up your code among different functions is up to you, but logically the division usually is such that each function performs a specific task.
Defining a Function
The general form of a C++ function definition is as follows –
return_type function_name( parameter list ) {
body of the function
}
Return Type − A function may return a value. The return_type is the data type of the value the function returns. Some functions perform the desired operations without returning a value. In this case, the return_type is the keyword void.
Function Name − This is the actual name of the function. The function name and the parameter list together constitute the function signature.
Parameters − A parameter is like a placeholder. When a function is invoked, you pass a value to the parameter. This value is referred to as actual parameter or argument. The parameter list refers to the type, order, and number of the parameters of a function. Parameters are optional; that is, a function may contain no parameters.
Function Body − The function body contains a collection of statements that define what the function does.
Example
Following is the source code for a function called max(). This function takes two parameters num1 and num2 and return the biggest of both −
// function returning the max between two numbers
int max(int num1, int num2)
{
// local variable declaration
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
Function Declarations
A function declaration tells the compiler about a function name and how to call the function. The actual body of the function can be defined separately.
A function declaration has the following parts −
return_type function_name( parameter list );
For the above defined function max(), following is the function declaration −
int max(int num1, int num2);
Parameter names are not important in function declaration only their type is required, so following is also valid declaration −
int max(int, int);
Function declaration is required when you define a function in one source file and you call that function in another file. In such case, you should declare the function at the top of the file calling the function.
Calling a Function
While creating a C++ function, you give a definition of what the function has to do. To use a function, you will have to call or invoke that function.
When a program calls a function, program control is transferred to the called function. A called function performs defined task and when it’s return statement is executed or when its function-ending closing brace is reached, it returns program control back to the main program.
To call a function, you simply need to pass the required parameters along with function name, and if function returns a value, then you can store returned value. For example −
#include <iostream>
using namespace std;
// function declaration
int max(int num1, int num2);
int main () {
// local variable declaration:
int a = 100;
int b = 200;
int ret;
// calling a function to get max value.
ret = max(a, b);
cout << "Max value is : " << ret << endl;
return 0;
}
// function returning the max between two numbers
int max(int num1, int num2) {
// local variable declaration
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
Q.42 How recursion works in C++?
Example 1: Factorial of a Number Using Recursion
// Factorial of n = 1*2*3*...*n
#include <iostream>
using namespace std;
int factorial(int);
int main()
{
int n;
cout<<"Enter a number to find factorial: ";
cin >> n;
cout << "Factorial of " << n <<" = " << factorial(n);
return 0;
}
int factorial(int n)
{
if (n > 1)
{
return n*factorial(n-1);
}
else
{
return 1;
}
}
Output
Enter a number to find factorial: 4
Factorial of 4 = 24
Q. 43 Write a short note in Array?
Arrays a kind of data structure that can store a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.
Instead of declaring individual variables, such as number0, number1, ..., and number99, you declare one array variable such as numbers and use numbers[0], numbers[1], and ..., numbers[99] to represent individual variables. A specific element in an array is accessed by an index.
All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.
Declaring Arrays
To declare an array in C, a programmer specifies the type of the elements and the number of elements required by an array as follows −
type arrayName [ arraySize ];
This is called a single-dimensional array. The arraySize must be an integer constant greater than zero and type can be any valid C data type. For example, to declare a 10-element array called balance of type double, use this statement −
double balance[10];
Here balance is a variable array which is sufficient to hold up to 10 double numbers.
Initializing Arrays
You can initialize an array in C either one by one or using a single statement as follows −
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
The number of values between braces { } cannot be larger than the number of elements that we declare for the array between square brackets [ ].
If you omit the size of the array, an array just big enough to hold the initialization is created. Therefore, if you write −
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
You will create exactly the same array as you did in the previous example. Following is an example to assign a single element of the array −
balance[4] = 50.0;
The above statement assigns the 5th element in the array with a value of 50.0. All arrays have 0 as the index of their first element which is also called the base index and the last index of an array will be total size of the array minus 1. Shown below is the pictorial representation of the array we discussed above –
#include <iostream>
using namespace std;
int main ()
{
int n[ 10 ]; /* n is an array of 10 integers */
int i,j;
/* initialize elements of array n to 0 */
for ( i = 0; i < 10; i++ ) {
n[ i ] = i + 100; /* set element at location i to i + 100 */
}
/* output each array element's value */
for (j = 0; j < 10; j++ ) {
cout<<"Element : " <<n[j]<<endl;
//cout<<"Element" <<" ["<<j<<"] :" <<n[j]<<endl;
}
return 0;
}
Output:
Element : 100
Element : 101
Element : 102
Element : 103
Element : 104
Element : 105
Element : 106
Element : 107
Element : 108
Element : 109
Q.44 Write a short note on Multi-dimensional array?
Two-dimensional Arrays
The simplest form of multidimensional array is the two-dimensional array. A two-dimensional array is, in essence, a list of one-dimensional arrays. To declare a two-dimensional integer array of size [x][y], you would write something as follows –
type arrayName [ x ][ y ];
Where type can be any valid C data type and arrayName will be a valid C identifier. A two-dimensional array can be considered as a table which will have x number of rows and y number of columns. A two-dimensional array a, which contains three rows and four columns can be shown as follows –
Thus, every element in the array a is identified by an element name of the form a[ i ][ j ], where 'a' is the name of the array, and 'i' and 'j' are the subscripts that uniquely identify each element in 'a'.
Initializing Two-Dimensional Arrays
Multidimensional arrays may be initialized by specifying bracketed values for each row. Following is an array with 3 rows and each row has 4 columns.
int a[3][4] = {
{0, 1, 2, 3} , /* initializers for row indexed by 0 */
{4, 5, 6, 7} , /* initializers for row indexed by 1 */
{8, 9, 10, 11} /* initializers for row indexed by 2 */
};
The nested braces, which indicate the intended row, are optional. The following initialization is equivalent to the previous example −
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
Accessing Two-Dimensional Array Elements
An element in a two-dimensional array is accessed by using the subscripts, i.e., row index and column index of the array. For example −
int val = a[2][3];
The above statement will take the 4th element from the 3rd row of the array. You can verify it in the above figure. Let us check the following program where we have used a nested loop to handle a two-dimensional array −
#include <iostream>
using namespace std;
int main ()
{
/* an array with 5 rows and 2 columns*/
int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};
int i, j;
/* output each array element's value */
for ( i=0; i<5; i++ )
{
for ( j=0; j<2; j++)
{
cout<<"a"<<"["<<i<<"]"<<"["<<j<<"]"<<"="<<a[i][j]<<endl;
}
}
return 0;
}
Output:
a[0][0]=0
a[0][1]=0
a[1][0]=1
a[1][1]=2
a[2][0]=2
a[2][1]=4
a[3][0]=3
a[3][1]=6
a[4][0]=4
a[4][1]=8
WAP in cpp to accept an m*n matrix and display it in natural form
#include<iostream>
using namespace std;
int main() {
int mat[3][3]; // matrix can have max 3 rows and 3 cols
int i, j;
cout << "Enter the matrix elements row-wise :- " << endl;
for ( i = 0; i < 3; i++ ) { // outer loop iterates over each row
for ( j = 0; j < 3; j++ ) { // inter loop iterates over each column
cout << "mat[" << i << "][" << j << "] : ";
// i -> row no. and j -> col no.
cin >> mat[i][j];
}
}
// display the matrix
cout << "You have entered the matrix :- " << endl;
for ( i = 0; i < 3; i++ ) {
for ( j = 0; j < 3; j++ ) {
cout << mat[i][j] << " ";
}
cout << endl;
}
return 0;
}
Output:
Enter the matrix elements row-wise :-
mat[0][0] : 1
mat[0][1] : 2
mat[0][2] : 3
mat[1][0] : 4
mat[1][1] : 5
mat[1][2] : 6
mat[2][0] : 7
mat[2][1] : 8
mat[2][2] : 9
You have entered the matrix :-
1 2 3
4 5 6
7 8 9
Strings
C++ provides following two types of string representations −
The C-Style Character String
The C-style character string originated within the C language and continues to be supported within C++. This string is actually a one-dimensional array of characters which is terminated by a null character '\0'. Thus a null-terminated string contains the characters that comprise the string followed by a null.
The following declaration and initialization create a string consisting of the word "Hello". To hold the null character at the end of the array, the size of the character array containing the string is one more than the number of characters in the word "Hello."
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
If you follow the rule of array initialization, then you can write the above statement as follows −
char greeting[] = "Hello";
Following is the memory presentation of above defined string in C/C++ −
C++ supports a wide range of functions that manipulate null-terminated strings –
Sr.No |
Function & Purpose |
1 |
strcpy(s1, s2); Copies string s2 into string s1. |
2 |
strcat(s1, s2); Concatenates string s2 onto the end of string s1. |
3 |
strlen(s1); Returns the length of string s1. |
4 |
strcmp(s1, s2); Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater than 0 if s1>s2. |
5 |
strchr(s1, ch); Returns a pointer to the first occurrence of character ch in string s1. |
6 |
strstr(s1, s2); Returns a pointer to the first occurrence of string s2 in string s1. |
#include <iostream>
#include <cstring>
using namespace std;
int main () {
char str1[10] = "Vision";
char str2[10] = "Victory";
char str3[10] = " ";
int len ;
// copy str1 into str3
strcpy( str3, str1);
cout << "strcpy( str3, str1) : " << str3 << endl;
// concatenates str1 and str2
strcat( str1, str2);
cout << "strcat( str1, str2): " << str1 << endl;
// total lenghth of str1 after concatenation
len = strlen(str1);
cout << "strlen(str1) : " << len << endl;
return 0;
}
#include <iostream>
#include<string>
#include<cstring>
using std::string;
using namespace std;
int main()
{
char nm[50],mm[50];
int a;
cout<<"Enter your name : "<<endl;
cin>>nm;
cout<<"Enter your name : "<<endl;
cin>>mm;
//a=strlen(nm);
cout<<"Length : "<<strlen(nm)<<endl;
cout<<"Length : "<<strlen(mm)<<endl;
cout<<"Concatination : "<<strcat(nm,mm);
//cout<<a;
return 0;
}
Output:
46. Explain Pointers in C++?
In earlier chapters, variables have been explained as locations in the computer's memory which can be accessed by their identifier (their name). This way, the program does not need to care about the physical address of the data in memory; it simply uses the identifier whenever it needs to refer to the variable.
For a C++ program, the memory of a computer is like a succession of memory cells, each one byte in size, and each with a unique address. These single-byte memory cells are ordered in a way that allows data representations larger than one byte to occupy memory cells that have consecutive addresses.
This way, each cell can be easily located in the memory by means of its unique address. For example, the memory cell with the address 1776 always follows immediately after the cell with address 1775 and precedes the one with 1777, and is exactly one thousand cells after 776 and exactly one thousand cells before 2776.
When a variable is declared, the memory needed to store its value is assigned a specific location in memory (its memory address). Generally, C++ programs do not actively decide the exact memory addresses where its variables are stored. Fortunately, that task is left to the environment where the program is run - generally, an operating system that decides the particular memory locations on runtime. However, it may be useful for a program to be able to obtain the address of a variable during runtime in order to access data cells that are at a certain position relative to it.
Address-of operator (&)
The address of a variable can be obtained by preceding the name of a variable with an ampersand sign (&), known as address-of operator.
For example:
|
foo = &myvar; |
|
This would assign the address of variable myvar to foo; by preceding the name of the variable myvar with the address-of operator (&), we are no longer assigning the content of the variable itself to foo, but its address.
The actual address of a variable in memory cannot be known before runtime, but let's assume, in order to help clarify some concepts, that myvar is placed during runtime in the memory address 1776. In this case, consider the following code fragment:
1 |
myvar = 25; foo = &myvar; bar = myvar; |
|
The values contained in each variable after the execution of this are shown in the following diagram:
First, we have assigned the value 25 to myvar (a variable whose address in memory we assumed to be 1776).
The second statement assigns foo the address of myvar, which we have assumed to be 1776.
Finally, the third statement, assigns the value contained in myvar to bar. This is a standard assignment operation, as already done many times in earlier chapters.
The main difference between the second and third statements is the appearance of the address-of operator (&).
The variable that stores the address of another variable (like foo in the previous example) is what in C++ is called a pointer. Pointers are a very powerful feature of the language that has many uses in lower level programming. A bit later, we will see how to declare and use pointers.
Dereference operator (*)
As just seen, a variable which stores the address of another variable is called a pointer. Pointers are said to "point to" the variable whose address they store.
An interesting property of pointers is that they can be used to access the variable they point to directly. This is done by preceding the pointer name with the dereference operator (*). The operator itself can be read as "value pointed to by".
Therefore, following with the values of the previous example, the following statement:
|
baz = *foo; |
|
This could be read as: "baz equal to value pointed to by foo", and the statement would actually assign the value 25 to baz, since foo is 1776, and the value pointed to by 1776 (following the example above) would be 25.
It is important to clearly differentiate that foo refers to the value 1776, while *foo (with an asterisk * preceding the identifier) refers to the value stored at address 1776, which in this case is 25. Notice the difference of including or not including the dereference operator (I have added an explanatory comment of how each of these two expressions could be read):
1 |
baz = foo; // baz equal to foo (1776) baz = *foo; // baz equal to value pointed to by foo (25) |
|
Q 47 Explain The reference and dereference operators are thus complementary:
& is the address-of operator, and can be read simply as "address of"
* is the dereference operator, and can be read as "value pointed to by"
Thus, they have sort of opposite meanings: An address obtained with & can be dereferenced with *.
Earlier, we performed the following two assignment operations:
1 |
myvar = 25; foo = &myvar; |
|
Right after these two statements, all of the following expressions would give true as result:
1 |
myvar == 25 &myvar == 1776 foo == 1776 *foo == 25 |
|
The first expression is quite clear, considering that the assignment operation performed on myvar was myvar=25. The second one uses the address-of operator (&), which returns the address of myvar, which we assumed it to have a value of 1776. The third one is somewhat obvious, since the second expression was true and the assignment operation performed on foo was foo=&myvar. The fourth expression uses the dereference operator (*) that can be read as "value pointed to by", and the value pointed to by foo is indeed 25.
So, after all that, you may also infer that for as long as the address pointed to by foo remains unchanged, the following expression will also be true:
|
*foo == myvar |
|
Declaring pointers
Due to the ability of a pointer to directly refer to the value that it points to, a pointer has different properties when it points to a char than when it points to an int or a float. Once dereferenced, the type needs to be known. And for that, the declaration of a pointer needs to include the data type the pointer is going to point to.
The declaration of pointers follows this syntax:
type * name;
where type is the data type pointed to by the pointer. This type is not the type of the pointer itself, but the type of the data the pointer points to. For example:
1 |
int * number; char * character; double * decimals; |
|
These are three declarations of pointers. Each one is intended to point to a different data type, but, in fact, all of them are pointers and all of them are likely going to occupy the same amount of space in memory (the size in memory of a pointer depends on the platform where the program runs). Nevertheless, the data to which they point to do not occupy the same amount of space nor are of the same type: the first one points to an int, the second one to a char, and the last one to a double. Therefore, although these three example variables are all of them pointers, they actually have different types: int*, char*, and double* respectively, depending on the type they point to.
Note that the asterisk (*) used when declaring a pointer only means that it is a pointer (it is part of its type compound specifier), and should not be confused with the dereference operator seen a bit earlier, but which is also written with an asterisk (*). They are simply two different things represented with the same sign.
Let's see an example on pointers:
// my first pointer
#include <iostream>
using namespace std;
int main ()
{
int firstvalue, secondvalue;
int * mypointer;
mypointer = &firstvalue;
*mypointer = 10;
mypointer = &secondvalue;
*mypointer = 20;
cout << "firstvalue is " << firstvalue << '\n';
cout << "secondvalue is " << secondvalue << '\n';
return 0;
}
Output:
firstvalue is 10
secondvalue is 20
Notice that even though neither firstvalue nor secondvalue are directly set any value in the program, both end up with a value set indirectly through the use of mypointer. This is how it happens:
First, mypointer is assigned the address of firstvalue using the address-of operator (&). Then, the value pointed to by mypointer is assigned a value of 10. Because, at this moment, mypointer is pointing to the memory location of firstvalue, this in fact modifies the value of firstvalue.
In order to demonstrate that a pointer may point to different variables during its lifetime in a program, the example repeats the process with secondvalue and that same pointer, mypointer.
Here is an example a little bit more elaborated:
// more pointers
#include <iostream>
using namespace std;
int main ()
{
int firstvalue = 5, secondvalue = 15;
int * p1, * p2;
p1 = &firstvalue; // p1 = address of firstvalue
p2 = &secondvalue; // p2 = address of secondvalue
*p1 = 10; // value pointed to by p1 = 10
*p2 = *p1; // value pointed to by p2 = value pointed to by p1
p1 = p2; // p1 = p2 (value of pointer is copied)
*p1 = 20; // value pointed to by p1 = 20
cout << "firstvalue is " << firstvalue << '\n';
cout << "secondvalue is " << secondvalue << '\n';
return 0;
}
Output:
firstvalue is 10
secondvalue is 20
Each assignment operation includes a comment on how each line could be read: i.e., replacing ampersands (&) by "address of", and asterisks (*) by "value pointed to by".
Notice that there are expressions with pointers p1 and p2, both with and without the dereference operator (*). The meaning of an expression using the dereference operator (*) is very different from one that does not. When this operator precedes the pointer name, the expression refers to the value being pointed, while when a pointer name appears without this operator, it refers to the value of the pointer itself (i.e., the address of what the pointer is pointing to).
Another thing that may call your attention is the line:
|
int * p1, * p2; |
|
This declares the two pointers used in the previous example. But notice that there is an asterisk (*) for each pointer, in order for both to have type int* (pointer to int). This is required due to the precedence rules. Note that if, instead, the code was:
|
int * p1, p2; |
|
p1 would indeed be of type int*, but p2 would be of type int. Spaces do not matter at all for this purpose. But anyway, simply remembering to put one asterisk per pointer is enough for most pointer users interested in declaring multiple pointers per statement. Or even better: use a different statement for each variable.
Q.48 Explain Pointers and arrays
The concept of arrays is related to that of pointers. In fact, arrays work very much like pointers to their first elements, and, actually, an array can always be implicitly converted to the pointer of the proper type. For example, consider these two declarations:
1 |
int myarray [20]; int * mypointer; |
|
The following assignment operation would be valid:
|
mypointer = myarray; |
|
After that, mypointer and myarray would be equivalent and would have very similar properties. The main difference being that mypointer can be assigned a different address, whereas myarray can never be assigned anything, and will always represent the same block of 20 elements of type int. Therefore, the following assignment would not be valid:
|
myarray = mypointer; |
|
// more pointers
#include <iostream>
using namespace std;
int main ()
{
int numbers[5];
int * p;
p = numbers; *p = 10;
p++; *p = 20;
p = &numbers[2]; *p = 30;
p = numbers + 3; *p = 40;
p = numbers; *(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
return 0;
}
Output:
10, 20, 30, 40, 50
Pointers and arrays support the same set of operations, with the same meaning for both. The main difference being that pointers can be assigned new addresses, while arrays cannot.
In the chapter about arrays, brackets ([]) were explained as specifying the index of an element of the array. Well, in fact these brackets are a dereferencing operator known as offset operator. They dereference the variable they follow just as * does, but they also add the number between brackets to the address being dereferenced. For example:
1 |
a[5] = 0; // a [offset of 5] = 0 *(a+5) = 0; // pointed to by (a+5) = 0 |
|
These two expressions are equivalent and valid, not only if a is a pointer, but also if a is an array. Remember that if an array, its name can be used just like a pointer to its first element.
Pointer initialization
Pointers can be initialized to point to specific locations at the very moment they are defined:
1 |
int myvar; int * myptr = &myvar; |
|
The resulting state of variables after this code is the same as after:
1 |
int myvar; int * myptr; myptr = &myvar; |
|
When pointers are initialized, what is initialized is the address they point to (i.e., myptr), never the value being pointed (i.e., *myptr). Therefore, the code above shall not be confused with:
1 |
int myvar; int * myptr; *myptr = &myvar; |
|
Which anyway would not make much sense (and is not valid code).
The asterisk (*) in the pointer declaration (line 2) only indicates that it is a pointer, it is not the dereference operator (as in line 3). Both things just happen to use the same sign: *. As always, spaces are not relevant, and never change the meaning of an expression.
Pointers can be initialized either to the address of a variable (such as in the case above), or to the value of another pointer (or array):
1 |
int myvar; int *foo = &myvar; int *bar = foo; |
|
Pointer Arithmetic’s
To conduct arithmetical operations on pointers is a little different than to conduct them on regular integer types. To begin with, only addition and subtraction operations are allowed; the others make no sense in the world of pointers. But both addition and subtraction have a slightly different behavior with pointers, according to the size of the data type to which they point.
When fundamental data types were introduced, we saw that types have different sizes. For example: char always has a size of 1 byte, short is generally larger than that, and int and long are even larger; the exact size of these being dependent on the system. For example, let's imagine that in a given system, char takes 1 byte, short takes 2 bytes, and long takes 4.
Suppose now that we define three pointers in this compiler:
1 |
char *mychar; short *myshort; long *mylong; |
|
and that we know that they point to the memory locations 1000, 2000, and 3000, respectively.
Therefore, if we write:
1 |
++mychar; ++myshort; ++mylong; |
|
mychar, as one would expect, would contain the value 1001. But not so obviously, myshort would contain the value 2002, and mylong would contain 3004, even though they have each been incremented only once. The reason is that, when adding one to a pointer, the pointer is made to point to the following element of the same type, and, therefore, the size in bytes of the type it points to is added to the pointer.
This is applicable both when adding and subtracting any number to a pointer. It would happen exactly the same if we wrote:
1 |
mychar = mychar + 1; myshort = myshort + 1; mylong = mylong + 1; |
|
Regarding the increment (++) and decrement (--) operators, they both can be used as either prefix or suffix of an expression, with a slight difference in behavior: as a prefix, the increment happens before the expression is evaluated, and as a suffix, the increment happens after the expression is evaluated. This also applies to expressions incrementing and decrementing pointers, which can become part of more complicated expressions that also include dereference operators (*). Remembering operator precedence rules, we can recall that postfix operators, such as increment and decrement, have higher precedence than prefix operators, such as the dereference operator (*). Therefore, the following expression:
|
*p++ |
|
is equivalent to *(p++). And what it does is to increase the value of p (so it now points to the next element), but because ++ is used as postfix, the whole expression is evaluated as the value pointed originally by the pointer (the address it pointed to before being incremented).
Essentially, these are the four possible combinations of the dereference operator with both the prefix and suffix versions of the increment operator (the same being applicable also to the decrement operator):
1 |
*p++ // same as *(p++): increment pointer, and dereference unincremented address *++p // same as *(++p): increment pointer, and dereference incremented address ++*p // same as ++(*p): dereference pointer, and increment the value it points to (*p)++ // dereference pointer, and post-increment the value it points to |
|
A typical -but not so simple- statement involving these operators is:
|
*p++ = *q++; |
|
Because ++ has a higher precedence than *, both p and q are incremented, but because both increment operators (++) are used as postfix and not prefix, the value assigned to *p is *q before both p and q are incremented. And then both are incremented. It would be roughly equivalent to:
1 |
*p = *q; ++p; ++q; |
|
Like always, parentheses reduce confusion by adding legibility to expressions.
Q.49 Explain Pointers and const
Pointers can be used to access a variable by its address, and this access may include modifying the value pointed. But it is also possible to declare pointers that can access the pointed value to read it, but not to modify it. For this, it is enough with qualifying the type pointed to by the pointer as const. For example:
1 |
int x; int y = 10; const int * p = &y; x = *p; // ok: reading p *p = x; // error: modifying p, which is const-qualified |
|
Here p points to a variable, but points to it in a const-qualified manner, meaning that it can read the value pointed, but it cannot modify it. Note also, that the expression &y is of type int*, but this is assigned to a pointer of type const int*. This is allowed: a pointer to non-const can be implicitly converted to a pointer to const. But not the other way around! As a safety feature, pointers to const are not implicitly convertible to pointers to non-const.
One of the use cases of pointers to const elements is as function parameters: a function that takes a pointer to non-const as parameter can modify the value passed as argument, while a function that takes a pointer to const as parameter cannot.
// pointers as arguments:
#include <iostream>
using namespace std;
void increment_all (int* start, int* stop)
{
int * current = start;
while (current != stop) {
++(*current); // increment value pointed
++current; // increment pointer
}
}
void print_all (const int* start, const int* stop)
{
const int * current = start;
while (current != stop) {
cout << *current << '\n';
++current; // increment pointer
}
}
int main ()
{
int numbers[] = {10,20,30};
increment_all (numbers,numbers+3);
print_all (numbers,numbers+3);
return 0;
}
Output:
11
21
31
Note that print_all uses pointers that point to constant elements. These pointers point to constant content they cannot modify, but they are not constant themselves: i.e., the pointers can still be incremented or assigned different addresses, although they cannot modify the content they point to.
And this is where a second dimension to constness is added to pointers: Pointers can also be themselves const. And this is specified by appending const to the pointed type (after the asterisk):
1 |
int x; int * p1 = &x; // non-const pointer to non-const int const int * p2 = &x; // non-const pointer to const int int * const p3 = &x; // const pointer to non-const int const int * const p4 = &x; // const pointer to const int |
|
The syntax with const and pointers is definitely tricky, and recognizing the cases that best suit each use tends to require some experience. In any case, it is important to get constness with pointers (and references) right sooner rather than later, but you should not worry too much about grasping everything if this is the first time you are exposed to the mix of const and pointers. More use cases will show up in coming chapters.
To add a little bit more confusion to the syntax of const with pointers, the const qualifier can either precede or follow the pointed type, with the exact same meaning:
1 |
const int * p2a = &x; // non-const pointer to const int int const * p2b = &x; // also non-const pointer to const int |
|
As with the spaces surrounding the asterisk, the order of const in this case is simply a matter of style. This chapter uses a prefix const, as for historical reasons this seems to be more extended, but both are exactly equivalent. The merits of each style are still intensely debated on the internet.
Pointers and string literals
As pointed earlier, string literals are arrays containing null-terminated character sequences. In earlier sections, string literals have been used to be directly inserted into cout, to initialize strings and to initialize arrays of characters.
But they can also be accessed directly. String literals are arrays of the proper array type to contain all its characters plus the terminating null-character, with each of the elements being of type const char (as literals, they can never be modified). For example:
|
const char * foo = "hello"; |
|
This declares an array with the literal representation for "hello", and then a pointer to its first element is assigned to foo. If we imagine that "hello" is stored at the memory locations that start at address 1702, we can represent the previous declaration as:
Note that here foo is a pointer and contains the value 1702, and not 'h', nor "hello", although 1702 indeed is the address of both of these.
The pointer foo points to a sequence of characters. And because pointers and arrays behave essentially in the same way in expressions, foo can be used to access the characters in the same way arrays of null-terminated character sequences are. For example:
1 |
*(foo+4) foo[4] |
|
Both expressions have a value of 'o' (the fifth element of the array).
Pointers to pointers
C++ allows the use of pointers that point to pointers, that these, in its turn, point to data (or even to other pointers). The syntax simply requires an asterisk (*) for each level of indirection in the declaration of the pointer:
1 |
char a; char * b; char ** c; a = 'z'; b = &a; c = &b; |
|
This, assuming the randomly chosen memory locations for each variable of 7230, 8092, and 10502, could be represented as:
With the value of each variable represented inside its corresponding cell, and their respective addresses in memory represented by the value under them.
The new thing in this example is variable c, which is a pointer to a pointer, and can be used in three different levels of indirection, each one of them would correspond to a different value:
c is of type char** and a value of 8092
*c is of type char* and a value of 7230
**c is of type char and a value of 'z'
Invalid pointers and null pointers
In principle, pointers are meant to point to valid addresses, such as the address of a variable or the address of an element in an array. But pointers can actually point to any address, including addresses that do not refer to any valid element. Typical examples of this are uninitialized pointers and pointers to nonexistent elements of an array:
1 |
int * p; // uninitialized pointer (local variable)
int myarray[10]; int * q = myarray+20; // element out of bounds |
|
Neither p nor q point to addresses known to contain a value, but none of the above statements causes an error. In C++, pointers are allowed to take any address value, no matter whether there actually is something at that address or not. What can cause an error is to dereference such a pointer (i.e., actually accessing the value they point to). Accessing such a pointer causes undefined behavior, ranging from an error during runtime to accessing some random value.
But, sometimes, a pointer really needs to explicitly point to nowhere, and not just an invalid address. For such cases, there exists a special value that any pointer type can take: the null pointer value. This value can be expressed in C++ in two ways: either with an integer value of zero, or with the nullptr keyword:
1 |
int * p = 0; int * q = nullptr; |
|
Here, both p and q are null pointers, meaning that they explicitly point to nowhere, and they both actually compare equal: all null pointers compare equal to other null pointers. It is also quite usual to see the defined constant NULL be used in older code to refer to the null pointer value:
|
int * r = NULL; |
|
NULL is defined in several headers of the standard library, and is defined as an alias of some null pointer constant value (such as 0 or nullptr).
Do not confuse null pointers with void pointers! A null pointer is a value that any pointer can take to represent that it is pointing to "nowhere", while a void pointer is a type of pointer that can point to somewhere without a specific type. One refers to the value stored in the pointer, and the other to the type of data it points to.
Q .50 Explain Pointers to functions
C++ allows operations with pointers to functions. The typical use of this is for passing a function as an argument to another function. Pointers to functions are declared with the same syntax as a regular function declaration, except that the name of the function is enclosed between parentheses () and an asterisk (*) is inserted before the name:
// pointer to functions
#include <iostream>
using namespace std;
int addition (int a, int b)
{ return (a+b); }
int subtraction (int a, int b)
{ return (a-b); }
int operation (int x, int y, int (*functocall)(int,int))
{
int g;
g = (*functocall)(x,y);
return (g);
}
int main ()
{
int m,n;
int (*minus)(int,int) = subtraction;
m = operation (7, 5, addition);
n = operation (20, m, minus);
cout <<n;
return 0;
}
Output:
8
Q.51 Explain Structure in C++?
Q.52 How to declare a structure in C++ programming?
The struct keyword defines a structure type followed by an identifier (name of the structure).
Then inside the curly braces, you can declare one or more members (declare variables inside curly braces) of that structure. For example:
struct Person
{
char name[50];
int age;
float salary;
};
Here a structure person is defined which has three members: name, age and salary.
When a structure is created, no memory is allocated.
The structure definition is only the blueprint for the creating of variables. You can imagine it as a datatype. When you define an integer as below:
int foo;
The int specifies that, variable foo can hold integer element only. Similarly, structure definition only specifies that, what property a structure variable holds when it is defined.
Note: Remember to end the declaration with a semicolon (;)
Q. 53 How to define a structure variable?
Once you declare a structure person as above. You can define a structure variable as:
Person bill;
Here, a structure variable bill is defined which is of type structure Person.
When structure variable is defined, only then the required memory is allocated by the compiler.
Considering you have either 32-bit or 64-bit system, the memory of float is 4 bytes, memory of int is 4 bytes and memory of char is 1 byte.
Hence, 58 bytes of memory is allocated for structure variable bill.
Example: C++ Structure
C++ Program to assign data to members of a structure variable and display it.
#include <iostream>
using namespace std;
struct Person
{
char name[50];
int age;
float salary;
};
int main()
{
Person p1;
cout << "Enter Full name: ";
cin.get(p1.name, 50);
cout << "Enter age: ";
cin >> p1.age;
cout << "Enter salary: ";
cin >> p1.salary;
cout << "\nDisplaying Information." << endl;
cout << "Name: " << p1.name << endl;
cout <<"Age: " << p1.age << endl;
cout << "Salary: " << p1.salary;
return 0;
}
Output
Enter Full name: Magdalena Dankova
Enter age: 27
Enter salary: 1024.4
Displaying Information.
Name: Magdalena Dankova
Age: 27
Salary:1024.4
Defining a union in C++
Union can be defined by the keyword union followed by list of member variables contained in curly braces.
union Employee{
int age;
long salary;
};
Here we have defined a union with the name union_name and it has two members i.e. age of type int and salary of type long.
Declaring the union in C
We can declare the union in various ways. By taking the above example we can declare the above defined union as.
union Employee{
int age;
long salary;
} employee;
So employee will be the variable of type Employee . We can also declare the above union as:
Employee employee;
Initializing a union
We can initialize the union in various ways. For example
union Employee{
int age;
long salary;
} employee={20000};
or we can initialize it as
employee.age= 30;
employee.salary=20000;
Normally when we declare the union it is allocated the memory that its biggest member can occupy. So here in our example employee will occupy the memory which a long type variable can occupy.
Similarly union values can be accessed via pointer variables
union Employee{
int age;
long salary;
} *employee;
(*employee).age;
or;
employee->age;
Q.54 Explain difference between Structure and Union?
Example of comparing size of union and structure
#include<iostream.h>
struct Employee1
{
int Id;
char Name[25];
long Salary;
};
union Employee2
{
int Id;
char Name[25];
long Salary;
};
void main()
{
cout << "\nSize of Employee1 is : " << sizeof(Employee1);
cout << "\nSize of Employee2 is : " << sizeof(Employee2);
}
Output :
Size of Employee1 is : 31
Size of Employee2 is : 25
UNIT II – Classes and Objects
Q.1 Define: Class, Objects.
Objects are the basic unit of OOP. They are instances of class, which have data members and use various member functions to perform tasks. You can imagine it to be similar to variable of class like we have variable of structure.
class Sample // class declaration
{
private: // access specifier
int a;
int b; // data members
public:
void function(); // member function
};
int main()
{
Sample s1; // s1 is an object of class Sample
//----- code----
return 0;
}
It is similar to structures in C language. Class can also be defined as user defined data type but it also contains functions in it. So, class is basically a blueprint for object. It declares & defines what data variables the object will have and what operations can be performed on the class's object. For examples, Mango, Apple and orange members of class fruit.
Classes are user-defined that types and behave like the built-in types of a programming language. The syntax used to create an object is not different then the syntax used to create an integer object in C. If fruit has been defines as a class, then the statement
Fruit Mango;
Will create an object mango belonging to the class fruit.
Example:
class C {
private:
int x;
public:
float f;
};
The public data members of objects of a class can be accessed using the direct member access operator (.). Let us try the following example to make the things clear:
#include <iostream>
using namespace std;
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
int main( )
{
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
// box 2 specification
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;
// volume of box 1
volume = Box1.height * Box1.length * Box1.breadth;
cout << "Volume of Box1 : " << volume <<endl;
// volume of box 2
volume = Box2.height * Box2.length * Box2.breadth;
cout << "Volume of Box2 : " << volume <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Volume of Box1 : 210
Volume of Box2 : 1560
It is important to note that private and protected members can not be accessed directly using direct member access operator (.). We will learn how private and protected members can be accessed.
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
double getVolume(void);// Returns box volume
};
Member functions can be defined within the class definition or separately using scope resolution operator, ::. Defining a member function within the class definition declares the function inline, even if you do not use the inline specifier. So either you can define Volume() function as below:
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
double getVolume(void)
{
return length * breadth * height;
}
};
If you like you can define same function outside the class using scope resolution operator, :: as follows:
double Box::getVolume(void)
{
return length * breadth * height;
}
Here, only important point is that you would have to use class name just before :: operator. A member function will be called using a dot operator (.) on a object where it will manipulate data related to that object only as follows:
Box myBox; // Create an object
myBox.getVolume(); // Call member function for the object
Let us put above concepts to set and get the value of different class members in a class:
#include <iostream>
using namespace std;
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
// Member functions declaration
double getVolume(void);
void setLength( double len );
void setBreadth( double bre );
void setHeight( double hei );
};
// Member functions definitions
double Box::getVolume(void)
{
return length * breadth * height;
}
void Box::setLength( double len )
{
length = len;
}
void Box::setBreadth( double bre )
{
breadth = bre;
}
void Box::setHeight( double hei )
{
height = hei;
}
// Main function for the program
int main( )
{
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 specification
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// volume of box 1
volume = Box1.getVolume();
cout << "Volume of Box1 : " << volume <<endl;
// volume of box 2
volume = Box2.getVolume();
cout << "Volume of Box2 : " << volume <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Volume of Box1 : 210
Volume of Box2 : 1560
2. List different methods of defining member function for a class.
Member Function
#include <iostream>
using namespace std;
class Box
{
double width;
public:
friend void printWidth(Box box);
void setWidth(double wid);
};
void Box::setWidth(double wid)
{
width=wid;
}
void printWidth(Box box)
{
cout<<"Width of box:"<<box.width<<endl;
}
int main()
{
Box box;
box.setWidth(10.0);
printWidth(box);
return 0;
}
Ans :
#include <iostream>
using namespace std;
class circle
{
int r;
float a;
public:
void read()
{
cout<<"Enter the value:"<<endl;
cin>>r;
}
void compute()
{
a=3.14*r*r;
}
void display()
{
cout<<"Area:"<<a;
}
};
int main()
{
circle c;
c.read();
c.compute();
c.display();
return 0;
}
Q.2 Explain the External Member Functionwith program example ?
Ans:
Return _type Class_name ::Function _name(argument list)
{
_
Statement ;
_
}
#include <iostream>
using namespace std;
class circle
{
int r;
float a;
public:
void read();
void compute();
void display();
};
void circle::read()
{
cout<<"Enter the value:"<<endl;
cin>>r;
}
void circle::compute()
{
a=3.14*r*r;
}
void circle:: display()
{
cout<<"Area:"<<a;
}
int main()
{
circle c;
c.read();
c.compute();
c.display();
return 0;
}
Q.3 Explain inline member function with program example .
Ans:
inline Return_type Class_name::Function_name(argument list)
{
_
Statements;
_
}
#include <iostream>
using namespace std;
class circle
{
int r;
float a;
public:
void read();
void compute();
void display();
};
inline void circle::read()
{
cout<<"Enter the value:"<<endl;
cin>>r;
}
inline void circle::compute()
{
a=3.14*r*r;
}
inline void circle:: display()
{
cout<<"Area:"<<a;
}
int main()
{
circle c;
c.read();
c.compute();
c.display();
return 0;
}
A friend function of a class is defined outside that class' scope but it has the right to access all private and protected members of the class. Even though the prototypes for friend functions appear in the class definition, friends are not member functions.
A friend can be a function, function template, or member function, or a class or class template, in which case the entire class and all of its members are friends.
To declare a function as a friend of a class, precede the function prototype in the class definition with keyword friend as follows:
#include <iostream>
using namespace std;
class Box
{
double width;
public:
friend void printWidth(Box box);
void setWidth(double wid);
};
void Box::setWidth(double wid)
{
width=wid;
}
void printWidth(Box box)
{
cout<<"Width of box:"<<box.width<<endl;
}
int main()
{
Box box;
box.setWidth(10.0);
printWidth(box);
return 0;
}
Example 2 :
class Box
{
double width;
public:
double length;
friend void printWidth( Box box );
void setWidth( double wid );
};
To declare all member functions of class ClassTwo as friends of class ClassOne, place a following declaration in the definition of class ClassOne:
friend class ClassTwo;
Consider the following program:
#include <iostream>
using namespace std;
class Box
{
double width;
public:
friend void printWidth( Box box );
void setWidth( double wid );
};
// Member function definition
void Box::setWidth( double wid )
{
width = wid;
}
// Note: printWidth() is not a member function of any class.
void printWidth( Box box )
{
/* Because printWidth() is a friend of Box, it can
directly access any member of this class */
cout << "Width of box : " << box.width <<endl;
}
// Main function for the program
int main( )
{
Box box;
// set box width without member function
box.setWidth(10.0);
// Use friend function to print the wdith.
printWidth( box );
return 0;
}
When the above code is compiled and executed, it produces the following result:
Width of box : 10
C++ Constructor basic concept
C++ Constructor Types
We will discuss different C++ constructor types in detail –
Q.6 Explain Default Constructor with the program and example ?
Syntax
class_name() {
-----
-----
}
Example of Default Constructor
Let us take the example of class Marks which contains the marks of two subjects Maths and Science.
#include<iostream>
using namespace std;
class Marks
{
public:
int maths;
int science;
//Default Constructor
Marks() {
maths=0;
science=0;
}
display() {
cout << "Maths : " << maths <<endl;
cout << "Science :" << science << endl;
}
};
int main() {
//invoke Default Constructor
Marks m;
m.display();
return 0;
}
Output :
Maths : 0
Science : 0
Q. 6 Explain Parametrized Constructor
This type of constructor can take the parameters.
Syntax
class_name(Argument_List) {
-----
-----
}
Example of Parametrized Constructor
Let us take the example of class ‘Marks’ which contains the marks of two subjects Maths and Science.
#include<iostream>
using namespace std;
class Marks
{
public:
int maths;
int science;
//Parametrized Constructor
Marks(int mark1,int mark2) {
maths = mark1;
science = mark2;
}
display() {
cout << "Maths : " << maths <<endl;
cout << "Science :" << science << endl;
}
};
int main() {
//invoke Parametrized Constructor
Marks m(90,85);
m.display();
return 0;
}
Output
Maths : 90
Science : 85
Q.7 Explain the Copy Constructor with example ?
Syntax
class_Name (const class_Name &obj) {
// body of constructor
}
Example of Copy Constructor
Let us take the example of class ‘Marks’ which contains the marks of two subjects Maths and Science.
#include<iostream>
using namespace std;
class marks
{
public:
int maths;
int science;
//Default Constructor
marks(){
maths=0;
science=0;
}
//Copy Constructor
marks(const marks &obj){
maths=obj.maths;
science=obj.science;
}
display(){
cout<<"Maths : " << maths
cout<<"Science : " << science;
}
};
int main(){
marks m1;
/*default constructor gets called
for initialization of m1 */
marks m2(const marks &m1);
//invoke Copy Constructor
m2.display();
return 0;
}
Output
Maths : 0
Science : 0
Q.8 Explain the concept of destructor with examples?
A destructor is used to destroy the memory allocated by the constructor.
The following points are to be noted about destructor.
~ClassName()
{
}
#include<iostream>
using namespace std;
class Marks
{
public:
int maths;
int science;
//constructor
Marks() {
cout << "Inside Constructor"<<endl;
cout << "C++ Object created"<<endl;
}
//Destructor
~Marks() {
cout << "Inside Destructor"<<endl;
cout << "C++ Object destructed"<<endl;
}
};
int main( )
{
Marks m1;
Marks m2;
return 0;
}
Output
Inside Constructor
C++ Object created
Inside Constructor
C++ Object created
Inside Destructor
C++ Object destructed
Inside Destructor
C++ Object destructed
Explanation :
You can see destructor gets called just before the return statement of main function. You can see destructor code below –
~Marks() {
cout << "Inside Destructor"<<endl;
cout << "C++ Object destructed"<<endl;
}
C++ Destructor always have same name as that of constructor but it just identified by tilde (~) symbol before constructor name.
Below example will show you how C++ destructor gets called just before C++ object goes out of scope.
#include<iostream>
using namespace std;
class Marks
{
public:
int maths;
int science;
//constructor
Marks() {
cout << "Inside Constructor"<<endl;
cout << "C++ Object created"<<endl;
}
//Destructor
~Marks() {
cout << "Inside Destructor"<<endl;
cout << "C++ Object destructed"<<endl;
}
\
g
};
int main( )
{
{
Marks m1;
}
cout<<"Hello World !!" <<endl;
cout<<"Hello World !!" <<endl;
cout<<"Hello World !!" <<endl;
cout<<"Hello World !!" <<endl;
return 0;
}
Output :
Inside Constructor
C++ Object created
Inside Destructor
C++ Object destructed
Hello World !!
Hello World !!
Hello World !!
Hello World !!
Explanation :
In this example we have defined the scope of the object as we declared object inside the curly braces i.e inside the inner block.
int main( )
{
{
Marks m1;
}
So object will be accessible only inside the curly block. Outside the curly block we cannot access the object so destructor gets called when inner curly block ends
In this example Hello World !! gets printed after the destructor. however for below example Hello World !! gets printed before constructor
#include<iostream>
using namespace std;
class Marks
{
public:
int maths;
int science;
//constructor
Marks() {
cout << "Inside Constructor"<<endl;
cout << "C++ Object created"<<endl;
}
//Destructor
~Marks() {
cout << "Inside Destructor"<<endl;
cout << "C++ Object destructed"<<endl;
}
};
int main( )
{
Marks m1;
cout<<"Hello World !!" <<endl;
cout<<"Hello World !!" <<endl;
cout<<"Hello World !!" <<endl;
cout<<"Hello World !!" <<endl;
return 0;
}
Output :
Inside Constructor
C++ Object created
Hello World !!
Hello World !!
Hello World !!
Hello World !!
Inside Destructor
C++ Object destructed
Difference Between Constructor and Destructor
Constructor and destructor are the special methods of every class.
|
Constructor |
Destructor |
Purpose |
Constructor is used to initialize the instance of a class. |
Destructor destroys the objects when they are no longer needed. |
When Called |
Constructor is Called when new instance of a class is created. |
Destructor is called when instance of a class is deleted or released. |
Memory Management |
Constructor allocates the memory. |
Destructor releases the memory. |
Arguments |
Constructors can have arguments. |
Destructor cannot have any arguments. |
Overloading |
Overloading of constructor is possible. |
Overloading of Destructor is not possible. |
Name |
Constructor has the same name as class name. |
Destructor also has the same name as class name but with (~) tiled operator. |
Syntax |
ClassName(Arguments) |
~ClassName() |
UNIT III – INHERITANCE
Inheritance in C++
Single Inheritance:
Multilevel Inheritance:
Multiple Inheritance:
Hybrid Inheritance:
Hierarchical Inheritance:
Q.1 Explain Inheritance in C++?
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
C++ Inheritance Syntax or Format
class base_class_name
{
..................
};
class derived_class_name : acess_specifier base_class_name
{
...........
} ;
Here is a simple program to illustrate the concept of inheritance in C++.
// inheritance.cpp
#include <iostream>
using namespace std;
class base
{
private:
int x;
public:
int y;
base()
{
x = 10;
y = 15;
}
};
class derive1 : public base //public derivation
{
public:
void display()
{
cout << "x of base class is not accessible" << endl;
cout << "value of y in base class = " << y;
}
};
int main() //main program
{
derive1 obj;
obj.display();
return 0;
} //end of program
Output
x of base class is not accessible
value of y in base class = 15
Explanation
In the above program, class derive1 is a public derivation of the base class base. As a result, derive1 inherits all the public members of base.
Hence, public members of the base class base is also a public member of the derived class derive1.
The private member of base is not inherited by derived class derive1.
Advantages and Disadvantages of Inheritance:
1. Reusability -- facility to use public methods of base class without rewriting the same
2. Extensibility -- extending the base class logic as per business logic of the derived class
3. Data hiding -- base class can decide to keep some data private so that it cannot be altered by the derived class
4. Overriding--With inheritance, we will be able to override the methods of the base class so that meaningful implementation of the base class method can be designed in the derived class.
5. Reliability -- The code increases its reliability. We can ensure that according to classification, the new derived class is used to adapt a feature from the base class.
Disadvantages:-
1. One of the main disadvantages of inheritance in C++(the same in other object-oriented languages) is the increased time/effort it takes the program to jump through all the levels of overloaded classes. If a given class has ten levels of abstraction above it, then it will essentially take ten jumps to run through a function defined in each of those classes
2. Main disadvantage of using inheritance is that the two classes (base and inherited class) get tightly coupled. This means one cannot be used independent of each other.
3. Also with time, during maintenance adding new features both base as well as derived classes are required to be changed. If a method signature is changed then we will be affected in both cases (inheritance & composition)
4. If a method is deleted in the "super class" or aggregate, then we will have to re-factor in case of using that method. Here things can get a bit complicated in case of inheritance because our programs will still compile, but the methods of the subclass will no longer be overriding superclass methods. These methods will become independent methods in their own right.
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:
• Constructors, destructors and copy constructors of the base class.
• Overloaded operators of the base class.
• The friend functions of the base class.
Q.2 Explain the different access specifiers in C++ MU-April 2017
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:
•Public Inheritance: When deriving a class from a public base class, public members of the base class become public members of the derived class and protected members of the base class become protected members of the derived class. A base class's private members are never accessible directly from a derived class, but can be accessed through calls to the public and protected members of the base class.
•Protected Inheritance: When deriving from a protected base class, public and protected members of the base class become protected members of the derived class.
•Private Inheritance: When deriving from a private base class, public and protected members of the base class become private members of the derived class.
Q.3 What is Single inheritance ? Explain with a program example .
As shown in the figure, in C++ single inheritance only one class can be derived from the base class. 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++ Programming Single Inheritance Syntax
class A // base class
{
..........
};
class B : acess_specifier A // derived class
{
...........
} ;
// inheritance.cpp
#include <iostream>
using namespace std;
class base //single base class
{
public:
int x;
void getdata()
{
cout << "Enter the value of x = "; cin >> x;
}
};
class derive : public base //single derived class
{
private:
int y;
public:
void readdata()
{
cout << "Enter the value of y = "; cin >> y;
}
void product()
{
cout << "Product = " << x * y;
}
};
int main()
{
derive a; //object of derived class
a.getdata();
a.readdata();
a.product();
return 0;
} //end of program
Output
Enter the value of x = 3
Enter the value of y = 4
Product = 12
In this program class derive is publicly derived from the base class base. So the class derive inherits all the protected and public members of base class base i.e the protected and the public members of base class are accessible from class derive.
However private members can’t be accessed, although, we haven’t used any private data members in the base class.
With the object of the derived class, we can call the functions of both derived and base class.
C++ Multilevel Inheritance Block Diagram
Here is the block diagram of C++ multilevel inheritance to make it clear.
As shown in above block diagram, class C has class B and class A as parent classes. Depending on the relation the level of inheritance can be extended to any level.
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++ Programming Multilevel Inheritance Syntax
class A // base class
{
...........
};
class B : acess_specifier A // derived class
{
...........
} ;
class C : access_specifier B // derived from derived class B
{
...........
} ;
Q.4 What is Multilevel Inheritance ? Explain with a program example .
// inheritance.cpp
#include <iostream>
using namespace std;
class base //single base class
{
public:
int x;
void getdata()
{
cout << "Enter value of x= "; cin >> x;
}
};
class derive1 : public base // derived class from base class
{
public:
int y;
void readdata()
{
cout << "\nEnter value of y= "; cin >> y;
}
};
class derive2 : public derive1 // derived from class derive1
{
private:
int z;
public:
void indata()
{
cout << "\nEnter value of z= "; cin >> z;
}
void product()
{
cout << "\nProduct= " << x * y * z;
}
};
int main()
{
derive2 a; //object of derived class
a.getdata();
a.readdata();
a.indata();
a.product();
return 0;
} //end of program
Output
Enter value of x= 2
Enter value of y= 3
Enter value of z= 3
Product= 18
Q.5 What is Multiple Inheritance ? Explain with a program example .
If a class is derived from two or more base classes then it is called multiple inheritance. In C++ multiple inheritance a derived class has more than one base class.
C++ Multiple Inheritance Block Diagram
Following block diagram highlights its structure.
As shown in above block diagram, class C is derived from two base classes A and B.
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++ Multiple Inheritance Syntax
class A
{
..........
};
class B
{
...........
} ;
class C : acess_specifier A,access_specifier B // derived class from A and B
{
...........
} ;
C++ Multiple Inheritance Example
// multiple inheritance.cpp
#include
using namespace std;
class A
{
public:
int x;
void getx()
{
cout << "enter value of x: "; cin >> x;
}
};
class B
{
public:
int y;
void gety()
{
cout << "enter value of y: "; cin >> y;
}
};
class C : public A, public B //C is derived from class A and class B
{
public:
void sum()
{
cout << "Sum = " << x + y;
}
};
int main()
{
C obj1; //object of derived class C
obj1.getx();
obj1.gety();
obj1.sum();
return 0;
} //end of program
Output
enter value of x: 5
enter value of y: 4
Sum = 9
Explanation
In the above program, there are two base class A and B from which class C is inherited. Therefore, derived class C inherits all the public members of A and B and retains their visibility. Here, we have created the object obj1 of derived class C.
Though but multiple and multilevel sounds like same but they differ hugely in meaning. In multilevel inheritance, we have multiple parent classes whereas in in multiple inheritance we have multiple base classes.
To put it in simple words, in multilevel inheritance, a class is derived from a class which is also derived from another base class. And these levels of inheritance can be extended. On the contrary, in multiple inheritance, a class is derived from two different base classes.
For example
Q.7 What is Hybrid Inheritance ? Explain with a program example .
The inheritance in which the derivation of a class involves more than one form of any inheritance is called hybrid inheritance. Basically C++ hybrid inheritance is combination of two or more types of inheritance. It can also be called multi path inheritance.
Following block diagram highlights the concept of hybrid inheritance which involves single and multiple inheritance.
C++ Hybrid Inheritance Block Diagram
Above block diagram shows the hybrid combination of single inheritance and multiple inheritance. Hybrid inheritance is used in a situation where we need to apply more than one inheritance in a program.
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++ Hybrid Inheritance Syntax
class A
{
.........
};
class B : public A
{
..........
} ;
class C
{
...........
};
class D : public B, public C
{
...........
};
As shown in block diagram class B is derived from class A which is single inheritance and then Class D is inherited from B and class C which is multiple inheritance. So single inheritance and multiple inheritance jointly results in hybrid inheritance.
Here is a simple program to illustrate the concept of hybrid inheritance in C++.
// hybrid inheritance.cpp
#include <iostream>
using namespace std;
class A
{
public:
int x;
};
class B : public A
{
public:
B() //constructor to initialize x in base class A
{
x = 10;
}
};
class C
{
public:
int y;
C() //constructor to initialize y
{
y = 4;
}
};
class D : public B, public C //D is derived from class B and class C
{
public:
void sum()
{
cout << "Sum= " << x + y;
}
};
int main()
{
D obj1; //object of derived class D
obj1.sum();
return 0;
} //end of program
Output
Sum= 14
C++ Hierarchical Inheritance
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
{
...........
} ;
// 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.
Q.8 Why is constructor required in derived class?
As long as the base class constructor accepts all the data member required for initializing, there is no need for having a constructor in the derived class . In case if the base class constructor accepts few data members and there are more data member in the derived class, then the derived class needs to have a constructor.
In case if the derived class has a constructor, then it is the responsibility of this constructor to call the base class constructor with the parameters required by it so as to initialize the variable in the base class constructor.
Thus whenever a derived class is made with a constructor, it is necessary to accept the arguments required by the derived class constructor as a well as the arguments required by the base class constructor. The base class constructor can be called first, and the arguments passed to it can be initialized and then the derived class constructor will be executed, with its parameters initialized.
Explain difference between Multiple and Hierarchical Inheritance
Sr.no |
Multiple Inheritance |
Hierarchical inheritance |
1. |
In this case a class is derived from multiples classes |
In this case there are multiple classes derived from one class |
2. |
In this case the derived class gets the access to allowed members of both base classes from which it is inherited. |
In this case the multiple derived classes get the access to the allowed members of one base class. |
Problem in multiple and hybrid Inheritance
Q.9 What are the issues in multiple and hybrid inheritance? how are they resolved ? Explain With a program Example.
Write a program to define the following relationship using hybrid inheritance
#include<iostream>
#include<conio.h>
#include<stdio.h>
using namespace std;
class Student
{
protected:
char name[20];
int roll_no;
};
class Test: public Student
{
protected:
int marks;
public:
void read()
{
cout<<"Enter name , roll number and marks obtained:";
gets(name);
cin>>roll_no>>marks;
}
};
class Sports
{
protected:
int score;
public:
void read()
{
cout<<"1. Student has won in national sports event\n 2. Student has not won in any national sports event\n Enter your choice:";
cin>>score;
}
};
class Result : public Test , public Sports
{
int total ;
public:
void calculate ()
{
if (score==1)
total=marks+15;
else
total=marks;
}
void display()
{
cout<<"The total is"<<total;
}
};
int main()
{
Result r;
//r.read(); // request for member 'read' is ambiguous
r.Test::read();
//r.read();// request for member 'read' is ambiguous
r.Sports::read();
r.calculate();
r.display();
return 0;
}
OUTPUT
Enter Name , roll number and marks obtained: Satish
24
96
1 . student has won in national sports event
2. student has not won in any national sports event
Enter your choice
The total is 96
Explanation
have a member function with the same name i.e.read(). The resolution to the problem can be seen in the main () function where the two function are called with specifying the class name along with the function name .
UNIT IV – POLYMORPHISM
OVERLOADING in C++
C++ allows you to specify more than one definition for a function name or an operator in the same scope, which is called function overloading and operator overloading respectively.
An overloaded declaration is a declaration that had been declared with the same name as a previously declared declaration in the same scope, except that both declarations have different arguments and obviously different definition (implementation).
When you call an overloaded function or operator, the compiler determines the most appropriate definition to use by comparing the argument types you used to call the function or operator with the parameter types specified in the definitions. The process of selecting the most appropriate overloaded function or operator is called overload resolution.
You can have multiple definitions for the same function name in the same scope. The definition of the function must differ from each other by the types and/or the number of arguments in the argument list. You cannot overload function declarations that differ only by return type.
Following is the example where same function print() is being used to print different data types:
#include <iostream>
using namespace std;
class printData
{
public:
void print(int i) {
cout << "Printing int: " << i << endl;
}
void print(double f) {
cout << "Printing float: " << f << endl;
}
void print(char* c) {
cout << "Printing character: " << c << endl;
}
};
int main(void)
{
printData pd;
// Call print to print integer
pd.print(5);
// Call print to print float
pd.print(500.263);
// Call print to print character
pd.print("Hello C++");
return 0;
}
When the above code is compiled and executed, it produces the following result:
Printing int: 5
Printing float: 500.263
Printing character: Hello C++
You can redefine or overload most of the built-in operators available in C++. Thus a programmer can use operators with user-defined types as well.
Overloaded operators are functions with special names the keyword operator followed by the symbol for the operator being defined. Like any other function, an overloaded operator has a return type and a parameter list.
Box operator+(const Box&);
declares the addition operator that can be used to add two Box objects and returns final Box object. Most overloaded operators may be defined as ordinary non-member functions or as class member functions. In case we define above function as non-member function of a class then we would have to pass two arguments for each operand as follows:
Box operator+(const Box&, const Box&);
Following is the example to show the concept of operator over loading using a member function. Here an object is passed as an argument whose properties will be accessed using this object, the object which will call this operator can be accessed using this operator as explained below:
#include <iosfr8tream>
using namespace std;
class Box
{
public:
double getVolume(void)
{
return length * breadth * height;
}
void setLength( double len )
{
length = len;
}
void setBreadth( double bre )
{
breadth = bre;
}
void setHeight( double hei )
{
height = hei;
}
// Overload + operator to add two Box objects.
Box operator+(const Box& b)
{
Box box;
box.length = this->length + b.length;
box.breadth = this->breadth + b.breadth;
box.height = this->height + b.height;
return box;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
// Main function for the program
int main( )
{
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box
Box Box3; // Declare Box3 of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 specification
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// volume of box 1
volume = Box1.getVolume();
cout << "Volume of Box1 : " << volume <<endl;
// volume of box 2
volume = Box2.getVolume();
cout << "Volume of Box2 : " << volume <<endl;
// Add two object as follows:
Box3 = Box1 + Box2;
// volume of box 3
volume = Box3.getVolume();
cout << "Volume of Box3 : " << volume <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400
Following is the list of operators which can be overloaded:
+ |
- |
* |
/ |
% |
^ |
& |
| |
~ |
! |
, |
= |
< |
> |
<= |
>= |
++ |
-- |
<< |
>> |
== |
!= |
&& |
|| |
+= |
-= |
/= |
%= |
^= |
&= |
|= |
*= |
<<= |
>>= |
[] |
() |
-> |
->* |
new |
new [] |
delete |
delete [] |
Following is the list of operators, which can not be overloaded:
:: |
.* |
. |
?: |
Here are various operator overloading examples to help you in understanding the concept.
S.N. |
Operators and Example |
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
Unary Operator Overloading :
The unary operators operate on a single operand and following are the examples of Unary operators:
The unary operators operate on the object for which they were called and normally, this operator appears on the left side of the object, as in !obj, -obj, and ++obj but sometime they can be used as postfix as well like obj++ or obj--.
Following example explain how minus (-) operator can be overloaded for prefix as well as postfix usage.
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 to infinite
int inches; // 0 to 12
public:
// required constructors
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
// method to display distance
void displayDistance()
{
cout << "F: " << feet << " I:" << inches <<endl;
}
// overloaded minus (-) operator
Distance operator- ()
{
feet = -feet;
inches = -inches;
return Distance(feet, inches);
}
};
int main()
{
Distance D1(11, 10), D2(-5, 11);
-D1; // apply negation
D1.displayDistance(); // display D1
-D2; // apply negation
D2.displayDistance(); // display D2
return 0;
}
When the above code is compiled and executed, it produces the following result:
F: -11 I:-10
F: 5 I:-11
Hope above example makes your concept clear and you can apply similar concept to overload Logical Not Operators (!).
Binary Operator Overloading:
The unary operators take two arguments and following are the examples of Binary operators. You use binary operators very frequently like addition (+) operator, subtraction (-) operator and division (/) operator.
Following example explains how addition (+) operator can be overloaded. Similar way, you can overload subtraction (-) and division (/) operators.
#include <iostream>
using namespace std;
class Box
{
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
public:
double getVolume(void)
{
return length * breadth * height;
}
void setLength( double len )
{
length = len;
}
void setBreadth( double bre )
{
breadth = bre;
}
void setHeight( double hei )
{
height = hei;
}
// Overload + operator to add two Box objects.
Box operator+(const Box& b)
{
Box box;
box.length = this->length + b.length;
box.breadth = this->breadth + b.breadth;
box.height = this->height + b.height;
return box;
}
};
// Main function for the program
int main( )
{
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box
Box Box3; // Declare Box3 of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 specification
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// volume of box 1
volume = Box1.getVolume();
cout << "Volume of Box1 : " << volume <<endl;
// volume of box 2
volume = Box2.getVolume();
cout << "Volume of Box2 : " << volume <<endl;
// Add two object as follows:
Box3 = Box1 + Box2;
// volume of box 3
volume = Box3.getVolume();
cout << "Volume of Box3 : " << volume <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400
Relational Operator Overloading:
There are various relational operators supported by C++ language like (<, >, <=, >=, ==, etc.) which can be used to compare C++ built-in data types.
You can overload any of these operators, which can be used to compare the objects of a class.
Following example explains how a < operator can be overloaded and similar way you can overload other relational operators.
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 to infinite
int inches; // 0 to 12
public:
// required constructors
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
// method to display distance
void displayDistance()
{
cout << "F: " << feet << " I:" << inches <<endl;
}
// overloaded minus (-) operator
Distance operator- ()
{
feet = -feet;
inches = -inches;
return Distance(feet, inches);
}
// overloaded < operator
bool operator <(const Distance& d)
{
if(feet < d.feet)
{
return true;
}
if(feet == d.feet && inches < d.inches)
{
return true;
}
return false;
}
};
int main()
{
Distance D1(11, 10), D2(5, 11);
if( D1 < D2 )
{
cout << "D1 is less than D2 " << endl;
}
Else
{
cout << "D2 is less than D1 " << endl;
}
return 0;
}
When the above code is compiled and executed, it produces the following result:
D2 is less than D1
Input Output Operator Overloading:
C++ is able to input and output the built-in data types using the stream extraction operator >> and the stream insertion operator <<. The stream insertion and stream extraction operators also can be overloaded to perform input and output for user-defined types like an object.
Here, it is important to make operator overloading function a friend of the class because it would be called without creating an object.
Following example explains how extraction operator >> and insertion operator <<.
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 to infinite
int inches; // 0 to 12
public:
// required constructors
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
friend ostream &operator<<( ostream &output,
const Distance &D )
{
output << "F : " << D.feet << " I : " << D.inches;
return output;
}
friend istream &operator>>( istream &input, Distance &D )
{
input >> D.feet >> D.inches;
return input;
}
};
int main()
{
Distance D1(11, 10), D2(5, 11), D3;
cout << "Enter the value of object : " << endl;
cin >> D3;
cout << "First Distance : " << D1 << endl;
cout << "Second Distance :" << D2 << endl;
cout << "Third Distance :" << D3 << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
$./a.out
Enter the value of object :
70
10
First Distance : F : 11 I : 10
Second Distance :F : 5 I : 11
Third Distance :F : 70 I : 10
Overloading Increment and Decrement Operators:
The increment (++) and decrement (--) operators are two important unary operators available in C++.
Following example explain how increment (++) operator can be overloaded for prefix as well as postfix usage. Similar way, you can overload operator (--).
#include <iostream>
using namespace std;
class Time
{
private:
int hours; // 0 to 23
int minutes; // 0 to 59
public:
// required constructors
Time(){
hours = 0;
minutes = 0;
}
Time(int h, int m){
hours = h;
minutes = m;
}
// method to display time
void displayTime()
{
cout << "H: " << hours << " M:" << minutes <<endl;
}
// overloaded prefix ++ operator
Time operator++ ()
{
++minutes; // increment this object
if(minutes >= 60)
{
++hours;
minutes -= 60;
}
return Time(hours, minutes);
}
// overloaded postfix ++ operator
Time operator++( int )
{
// save the orignal value
Time T(hours, minutes);
// increment this object
++minutes;
if(minutes >= 60)
{
++hours;
minutes -= 60;
}
// return old original value
return T;
}
};
int main()
{
Time T1(11, 59), T2(10,40);
++T1; // increment T1
T1.displayTime(); // display T1
++T1; // increment T1 again
T1.displayTime(); // display T1
T2++; // increment T2
T2.displayTime(); // display T2
T2++; // increment T2 again
T2.displayTime(); // display T2
return 0;
}
When the above code is compiled and executed, it produces the following result:
H: 12 M:0
H: 12 M:1
H: 10 M:41
H: 10 M:42
Assignment Operator Overloading :
You can overload the assignment operator (=) just as you can other operators and it can be used to create an object just like the copy constructor.
Following example explains how an assignment operator can be overloaded.
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 to infinite
int inches; // 0 to 12
public:
// required constructors
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
void operator=(const Distance &D )
{
feet = D.feet;
inches = D.inches;
}
// method to display distance
void displayDistance()
{
cout << "F: " << feet << " I:" << inches << endl;
}
};
int main()
{
Distance D1(11, 10), D2(5, 11);
cout << "First Distance : ";
D1.displayDistance();
cout << "Second Distance :";
D2.displayDistance();
// use assignment operator
D1 = D2;
cout << "First Distance :";
D1.displayDistance();
return 0;
}
When the above code is compiled and executed, it produces the following result:
First Distance : F: 11 I:10
Second Distance :F: 5 I:11
First Distance :F: 5 I:11
The subscript operator [] is normally used to access array elements. This operator can be overloaded to enhance the existing functionality of C++ arrays.
Following example explains how a subscript operator [] can be overloaded.
#include <iostream>
using namespace std;
const int SIZE = 10;
class safearay
{
private:
int arr[SIZE];
public:
safearay()
{
register int i;
for(i = 0; i < SIZE; i++)
{
arr[i] = i;
}
}
int &operator[](int i)
{
if( i > SIZE )
{
cout << "Index out of bounds" <<endl;
// return first element.
return arr[0];
}
return arr[i];
}
};
int main()
{
safearay A;
cout << "Value of A[2] : " << A[2] <<endl;
cout << "Value of A[5] : " << A[5]<<endl;
cout << "Value of A[12] : " << A[12]<<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Value of A[2] : 2
Value of A[5] : 5
Index out of bounds
Value of A[12] : 0
Data abstraction refers to, providing only essential information to the outside world and hiding their background details, i.e., to represent the needed information in program without presenting the details.
Data abstraction is a programming (and design) technique that relies on the separation of interface and implementation.
Data abstraction provides two important advantages:
By defining data members only in the private section of the class, the class author is free to make changes in the data. If the implementation changes, only the class code needs to be examined to see what affect the change may have. If data are public, then any function that directly accesses the data members of the old representation might be broken.
Any C++ program where you implement a class with public and private members is an example of data abstraction. Consider the following example:
#include <iostream>
using namespace std;
class Adder{
public:
// constructor
Adder(int i = 0)
{
total = i;
}
// interface to outside world
void addNum(int number)
{
total += number;
}
// interface to outside world
int getTotal()
{
return total;
};
private:
// hidden data from outside world
int total;
};
int main( )
{
Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
cout << "Total " << a.getTotal() <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Total 60
Data encapsulation is a mechanism of bundling the data, and the functions that use them and data abstraction is a mechanism of exposing only the interfaces and hiding the implementation details from the user.
C++ supports the properties of encapsulation and data hiding through the creation of user-defined types, called classes. We already have studied that a class can contain private, protected and public members. By default, all items defined in a class are private. For
Any C++ program where you implement a class with public and private members is an example of data encapsulation and data abstraction. Consider the following example:
#include <iostream>
using namespace std;
class Adder{
public:
// constructor
Adder(int i = 0)
{
total = i;
}
// interface to outside world
void addNum(int number)
{
total += number;
}
// interface to outside world
int getTotal()
{
return total;
};
private:
// hidden data from outside world
int total;
};
int main( )
{
Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
cout << "Total " << a.getTotal() <<endl;
return 0;}
When the above code is compiled and executed, it produces the following result:
Total 60
Polymorphism in C++
The word polymorphism means having many forms. Typically, polymorphism occurs when there is a hierarchy of classes and they are related by inheritance.
C++ polymorphism means that a call to a member function will cause a different function to be executed depending on the type of object that invokes the function.
Consider the following example where a base class has been derived by other two classes:
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// Main function for the program
int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
// store the address of Rectangle
shape = &rec;
// call rectangle area.
shape->area();
// store the address of Triangle
shape = &tri;
// call triangle area.
shape->area();
return 0;
}
When the above code is compiled and executed, it produces the following result:
Parent class area
Parent class area
The reason for the incorrect output is that the call of the function area() is being set once by the compiler as the version defined in the base class. This is called static resolution of the function call, or static linkage - the function call is fixed before the program is executed. This is also sometimes called early binding because the area() function is set during the compilation of the program.
But now, let's make a slight modification in our program and precede the declaration of area() in the Shape class with the keyword virtual so that it looks like this:
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
After this slight modification, when the previous example code is compiled and executed, it produces the following result:
Rectangle class area
Triangle class area
This time, the compiler looks at the contents of the pointer instead of it's type. Hence, since addresses of objects of tri and rec classes are stored in *shape the respective area() function is called.
As you can see, each of the child classes has a separate implementation for the function area(). This is how polymorphism is generally used. You have different classes with a function of the same name, and even the same parameters, but with different implementations.
Types of Polymorphism:
C++ provides two different types of polymorphism.
1. Run-time
2. Compile-time
Run-time:
The appropriate member function could be selected while the programming is running. This is known as run-time polymorphism. The run-time polymorphism is implemented with inheritance and virtual functions.
Compile-time:
The compiler is able to select the appropriate function for a particular call at compile-time itself. This is known as compile-time polymorphism. The compile-time polymorphism is implemented with templates.
A virtual function is a function in a base class that is declared using the keyword virtual. Defining in a base class a virtual function, with another version in a derived class, signals to the compiler that we don't want static linkage for this function.
What we do want is the selection of the function to be called at any given point in the program to be based on the kind of object for which it is called. This sort of operation is referred to as dynamic linkage, or late binding.
It's possible that you'd want to include a virtual function in a base class so that it may be redefined in a derived class to suit the objects of that class, but that there is no meaningful definition you could give for the function in the base class.
We can change the virtual function area() in the base class to the following:
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
// pure virtual function
virtual int area() = 0;
};
The = 0 tells the compiler that the function has no body and above virtual function will be called pure virtual function.
UNIT 5
File Operations in C++
Managing Console I/O Operations
The C++ I/O system supplies an interface to the programmer that is independent of the actual device being accessed. This interface is known as stream. The I/O system contains a hierarchy of the stream classes used to define various streams to deal with the console and disk files. These classes are known as stream classes. The base stream class for handling input and output operations with the console and disk is ios and there are various classes derived from it such as istream, ostream, streambuf etc.
The header file <iostream> declares the stream classes.
As part of the library, the iostream declares certain objects that are used to perform input and output operations. These are known as Stream objects. They are cin, cout, cerr, clog etc.
Standard streams in C++
A standard stream is a pre-connected stream provided to a computer program by it’s environment. C++ comes with four predefined standard stream objects that have already been set up for your use. The first two, you have seen before:
Unbuffered output is typically handled immediately, whereas buffered output is typically stored and written out as a block. Because clog isn’t used very often, it is often omitted from the list of standard streams.
A basic example
Here’s an example of input and output using the standard streams:
|
#include <iostream>
int main() { using namespace std; // First we'll use the insertion operator on cout to print text to the monitor cout << "Enter your age: " << endl;
// Then we'll use the extraction operator on cin to get input from the user int nAge; cin >> nAge;
if (nAge <= 0) { // In this case we'll use the insertion operatior on cerr to print an error message cerr << "Oops, you entered an invalid age!" << endl; exit(1); }
// Otherwise we'll use insertion again on cout to print a result cout << "You entered " << nAge << " years old" << endl;
return 0; } |
Hope you already understand the concept of C++ Template which we already have discussed in one of the chapters. The C++ STL (Standard Template Library) is a powerful set of C++ template classes to provides general-purpose templatized classes and functions that implement many popular and commonly used algorithms and data structures like vectors, lists, queues, and stacks.
At the core of the C++ Standard Template Library are following three well-structured components:
Component |
Description |
Containers |
Containers are used to manage collections of objects of a certain kind. There are several different types of containers like deque, list, vector, map etc. |
Algorithms |
Algorithms act on containers. They provide the means by which you will perform initialization, sorting, searching, and transforming of the contents of containers. |
Iterators |
Iterators are used to step through the elements of collections of objects. These collections may be containers or subsets of containers. |
We will discuss about all the three C++ STL components in next chapter while discussing C++ Standard Library. For now, keep in mind that all the three components have a rich set of pre-defined functions which help us in doing complicated tasks in very easy fashion.
Let us take the following program demonstrates the vector container (a C++ Standard Template) which is similar to an array with an exception that it automatically handles its own storage requirements in case it grows:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// create a vector to store int
vector<int> vec;
int i;
// display the original size of vec
cout << "vector size = " << vec.size() << endl;
// push 5 values into the vector
for(i = 0; i < 5; i++){
vec.push_back(i);
}
// display extended size of vec
cout << "extended vector size = " << vec.size() << endl;
// access 5 values from the vector
for(i = 0; i < 5; i++){
cout << "value of vec [" << i << "] = " << vec[i] << endl;
}
// use iterator to access the values
vector<int>::iterator v = vec.begin();
while( v != vec.end()) {
cout << "value of v = " << *v << endl;
v++;
}
return 0;
}
When the above code is compiled and executed, it produces the following result:
vector size = 0
extended vector size = 5
value of vec [0] = 0
value of vec [1] = 1
value of vec [2] = 2
value of vec [3] = 3
value of vec [4] = 4
value of v = 0
value of v = 1
value of v = 2
value of v = 3
value of v = 4
Here are following points to be noted related to various functions we used in the above example:
Unformatted Input/Output is the most basic form of input/output. Unformatted input/output transfers the internal binary representation of the data directly between memory and the file. Formatted output converts the internal binary representation of the data to ASCII characters which are written to the output file. Formatted input reads characters from the input file and converts them to internal form. Formatted I/O can be either "Free" format or "Explicit" format, as described below.
Unformatted input/output is the simplest and most efficient form of input/output. It is usually the most compact way to store data. Unformatted input/output is the least portable form of input/output. Unformatted data files can only be moved easily to and from computers that share the same internal data representation. It should be noted that XDR (eXternal Data Representation) files, described in Portable Unformatted Input/Output, can be used to produce portable binary data. Unformatted input/output is not directly human readable, so you cannot type it out on a terminal screen or edit it with a text editor.
Formatted input/output is very portable. It is a simple process to move formatted data files to various computers, even computers running different operating systems, as long as they all use the ASCII character set. (ASCII is the American Standard Code for Information Interchange. It is the character set used by almost all current computers, with the notable exception of large IBM mainframes.) Formatted files are human readable and can be typed to the terminal screen or edited with a text editor.
However, formatted input/output is more computationally expensive than unformatted input/output because of the need to convert between internal binary data and ASCII text. Formatted data requires more space than unformatted to represent the same information. Inaccuracies can result when converting data between text and the internal representation.
So far, we have been using the iostream standard library, which providescin and cout methods for reading from standard input and writing to standard output respectively.
This tutorial will teach you how to read and write from a file. This requires another standard C++ library called fstream, which defines three new data types:
Data Type |
Description |
ofstream |
This data type represents the output file stream and is used to create files and to write information to files. |
ifstream |
This data type represents the input file stream and is used to read information from files. |
fstream |
This data type represents the file stream generally, and has the capabilities of both ofstream and ifstream which means it can create files, write information to files, and read information from files. |
To perform file processing in C++, header files <iostream> and <fstream> must be included in your C++ source file.
A file must be opened before you can read from it or write to it. Either theofstream or fstream object may be used to open a file for writing and ifstream object is used to open a file for reading purpose only.
Following is the standard syntax for open() function, which is a member of fstream, ifstream, and ofstream objects.
void open(const char *filename, ios::openmode mode);
Here, the first argument specifies the name and location of the file to be opened and the second argument of the open() member function defines the mode in which the file should be opened.
Mode Flag |
Description |
ios::app |
Append mode. All output to that file to be appended to the end. |
ios::ate |
Open a file for output and move the read/write control to the end of the file. |
ios::in |
Open a file for reading. |
ios::out |
Open a file for writing. |
ios::trunc |
If the file already exists, its contents will be truncated before opening the file. |
You can combine two or more of these values by ORing them together. For example if you want to open a file in write mode and want to truncate it in case it already exists, following will be the syntax:
ofstream outfile;
outfile.open("file.dat", ios::out | ios::trunc );
Similar way, you can open a file for reading and writing purpose as follows:
fstream afile;
afile.open("file.dat", ios::out | ios::in );
When a C++ program terminates it automatically closes flushes all the streams, release all the allocated memory and close all the opened files. But it is always a good practice that a programmer should close all the opened files before program termination.
Following is the standard syntax for close() function, which is a member of fstream, ifstream, and ofstream objects.
void close();
While doing C++ programming, you write information to a file from your program using the stream insertion operator (<<) just as you use that operator to output information to the screen. The only difference is that you use an ofstream or fstream object instead of the cout object.
You read information from a file into your program using the stream extraction operator (>>) just as you use that operator to input information from the keyboard. The only difference is that you use an ifstream orfstream object instead of the cin object.
Following is the C++ program which opens a file in reading and writing mode. After writing information inputted by the user to a file named afile.dat, the program reads information from the file and outputs it onto the screen:
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
char data[100];
// open a file in write mode.
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
cin.getline(data, 100);
// write inputted data into the file.
outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();
// again write inputted data into the file.
outfile << data << endl;
// close the opened file.
outfile.close();
// open a file in read mode.
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// write the data at the screen.
cout << data << endl;
// again read the data from the file and display it.
infile >> data;
cout << data << endl;
// close the opened file.
infile.close();
return 0;
}
When the above code is compiled and executed, it produces the following sample input and output:
$./a.out
Writing to the file
Enter your name: Zara
Enter your age: 9
Reading from the file
Zara
9
Above examples make use of additional functions from cin object, like getline() function to read the line from outside and ignore() function to ignore the extra characters left by previous read statement.
Both istream and ostream provide member functions for repositioning the file-position pointer. These member functions are seekg ("seek get") for istream and seekp ("seek put") for ostream.
The argument to seekg and seekp normally is a long integer. A second argument can be specified to indicate the seek direction. The seek direction can be ios::beg (the default) for positioning relative to the beginning of a stream, ios::cur for positioning relative to the current position in a stream or ios::end for positioning relative to the end of a stream.
The file-position pointer is an integer value that specifies the location in the file as a number of bytes from the file's starting location. Some examples of positioning the "get" file-position pointer are:
// position to the nth byte of fileObject (assumes ios::beg)
fileObject.seekg( n );
// position n bytes forward in fileObject
fileObject.seekg( n, ios::cur );
// position n bytes back from end of fileObject
fileObject.seekg( n, ios::end );
// position at end of fileObject
fileObject.seekg( 0, ios::end );