Allied Subject II IV Semester
II Year Subject Code : SMTJA42
PROGRAMMING WITH C++
UNIT - 1
Principles of object oriented programming - basic concepts of oops- benefits-introduction to C++ - token - keywords - identifiers and constants - data types -symbolic constants- operators-expressions and control structures.
UNIT - II
Functions - function prototyping - call by reference - return by reference –inline functions- default arguments-constant arguments-function overloading -friend and virtual functions- Math library functions.
UNIT - III
Classes and objects - arrays within a class - memory allocation for objects - static data members, functions-arrays of objects - friendly functions - returning objects - pointers to members-local classes.
UNIT - IV
Constructors- parameterized, multiple constructor- copy constructor - dynamic constructors -constructing two dimensional arrays- destructors.
UNIT - V
Operator overloading - overloading unary operators - overloading binary operators - rules for overloading operators - defining derived classes - inheritance and their types.
Text Book E Balagurusamy , Object-Oriented Programming with C++, Tata McGraw-Hill Publishing Company Limited, New Delhi, 2008.
Introduction
Programmers write instructions in various programming languages to perform their computation tasks such as:
Machine level Language
Assembly level Language
High level Language
Machine level Language
Machine code or machine language is a set of instructions executed directly by a computer’s central processing unit (CPU). Each instruction performs a very specific task, such as a load, a jump, or an ALU operation on a unit of data in a CPU register or memory. Every program directly executed by a CPU is made up of a series of such instructions.
Assembly level Language
An assembly language (or assembler language) is a low-level programming language for a computer, or other programmable device, in which there is a very strong (generally one-to-one) correspondence between the language and the architecture’s machine code instructions. Assembly language is converted into executable machine code by a utility program referred to as an assembler; the conversion process is referred to as assembly, or assembling the code.
High level Language
High-level language is any programming language that enables development of a program in much simpler programming context and is generally independent of the computer’s hardware architecture. High-level language has a higher level of abstraction from the computer, and focuses more on the programming logic rather than the underlying hardware components such as memory addressing and register utilization.
The first high-level programming languages were designed in the 1950s. Now there are dozens of different languages, including Ada , Algol, BASIC, COBOL, C, C++, JAVA, FORTRAN, LISP, Pascal, and Prolog. Such languages are considered high-level because they are closer to human languages and farther from machine languages. In contrast, assembly languages are considered low- level because they are very close to machine languages.
The high-level programming languages are broadly categorized in to two categories:
Procedure oriented programming(POP) language.
Object oriented programming(OOP) language.
Procedure Oriented Programming Language
In the procedure oriented approach, the problem is viewed as sequence of things to be done such as reading , calculation and printing.
Procedure oriented programming basically consist of writing a list of instruction or actions for the computer to follow and organizing these instruction into groups known as functions.
The disadvantage of the procedure oriented programming languages is:
Global data access
It does not model real word problem very well
No data hiding
Characteristics of procedure oriented programming:
Emphasis is on doing things(algorithm)
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
Function transforms data from one form to another.
Employs top-down approach in program design
1 Principles of Object Oriented Programming
1.1 Object Oriented Programing
“Object oriented programming as an approach that provides a way of modularizing programs by creating partitioned memory area for both data and functions that can be used as templates for creating copies of such modules on demand”.
1.1.1 Features of the Object Oriented programming
Emphasis is on doing rather than procedure.
Programs are divided into what are known as objects.
Data structures are designed such that they characterize the objects.
Functions that operate on the data of an object are tied together in the data structure.
Data is hidden and can’t be accessed by external functions.
Objects may communicate with each other through functions.
New data and functions can be easily added.
Follows bottom-up approach in program design.
1.2 Basic Concepts of Object-Oriented Programming
It is necessary to understand some of the concepts used extensively in object-oriented programming These include:
Objects
Classes
Data abstraction and encapsulation
Inheritance
Polymorphism
Dynamic binding
Message passing
1.2.1 Objects
Objects are the basic run-time entities in an object-oriented system. They may represent a person, a place, a bank account, a table of data or any item that the program must handle.
The fundamental idea behind object oriented approach is to combine both data and function into a single unit and these units are called objects.
The term objects means a combination of data and program that represent some real word entity. For example: consider an example named Amit; Amit is 25 years old and his salary is 2500. The Amit may be represented in a computer program as an object. The data part of the object would be (name: Amit, age: 25, salary: 2500)
The program part of the object may be collection of programs (retrive of data, change age, change of salary). In general even any user –defined type-such as employee may be used. In the Amit object the name, age and salary are called attributes of the object.
1.2.2 Class
A group of objects that share common properties for data part and some program part are collectively called as class.
In C++ a class is a new data type that contains member variables and member functions that operate on the variables.
1.2.3 Data Abstraction
Abstraction refers to the act of representing essential features without including the back ground details or explanations. Classes use the concept of abstraction and are defined as size, width and cost and functions to operate on the attributes.
1.2.4 Data Encapsulation
The wrapping up of data and function into a single unit (called class) is known as encapsulation. The data is not accessible to the outside world and only those functions which are wrapped in the class can access it. These functions provide the interface between the objects data and the program.
1.2.5 Inheritance
Inheritance is the process by which objects of one class acquire the properties of another class. In the concept of inheritance provides the idea of reusablity. This mean that we can add additional features to an existing class with out modifying it. This is possible by desining a new class will have the combined features of both the classes.
1.2.6 Polymorphism
Polymorphism means the ability to take more than one form. An operation may exhibit different instance. The behaviour depends upon the type of data used in the operation.
A language feature that allows a function or operator to be given more than one definition. The types of the arguments with which the function or operator is called determines which definition will be used.
Overloading may be operator overloading or function overloading.
It is able to express the operation of addition by a single operator say ‘+’. When this is possible you use the expression x + y to denote the sum of x and y, for many different types of x and y; integers , float and complex no. You can even define the + operation for two strings to mean the concatenation of the strings.
1.2.7 Dynamic Binding
Binding refers to the linking of a procedure call to the code to the executed in response to the call. Dynamic binding means the code associated with a given procedure call is not known untill the time of the call at run-time. It is associated with a polymorphic reference depends upon the dynamic type of that reference.
1.2.8 Message Passing
An object oriented program consists of a set of objects that communicate with each other.
The proceed of programming in an object-oriented language, therefore, involves the following basic steps
Creating dashes that define objects and their behaviour,
Creating objects from class definitions, and
Establishing communication among objects.
Objects communicate with one another by sending end receiving information much the same way as people pass messages to one another. The concept of message passing makes it easier to talk about building systems that directly model or simulate their real-world counterparts.
A message for an object is a request for execution of a procedure and therefore will invoke a function (procedure) in the receiving object that generates the desired result. Message passing involves specifying the name of the object, the name of the function (message) and information to be sent.
1.3 Benefits of OOP
OOP offers several benefits to both the program designer and the user. Object-oriented contributes to the solution of many problems associated with the development and quality of software products. The principal advantages are
Through inheritance we can eliminate redundant code and extend the use of existing classes.
We can build programs from the standard working modules that communicate with one another, rather than having to start writing the code from scratch. This leads to saving of development time and higher productivity.
This principle of data hiding helps the programmer to build secure programs that can’t be invaded by code in other parts of the program.
It is possible to have multiple instances of an object to co-exist with out any interference.
It is easy to partition the work in a project based on objects.
Object-oriented systems can be easily upgraded from small to large systems.
Message passing techniques for communication between objects makes the interface description with external systems much simpler.
Software complexity can be easily managed.
1.4 Application of OOP
The most popular application of OOPs up to now, has been in the area of user interface design such as windows. There are hundreds of windowing systems developed using OOP techniques.
Real business systems are often much more complex and contain many more objects with complicated attributes and methods. OOP is useful in this type of applications because it can simplify a complex problem. The promising areas for application of OOP includes.
Real – Time systems.
Simulation and modeling
Object oriented databases.
Hypertext, hypermedia and expertext.
Al and expert systems.
Neural networks and parallel programming.
Decision support and office automation systems.
CIM / CAM / CAD system.
1.5 What is C++ ?
C++ is an object oriented programming language, C++ was developed by Bjarne Stroustrup at AT & T Bell lab, USA in early eighties. C++ was developed from C and simula67 language. C++ was early called ‘C with classes’.
1.5.1 A Simple C++ Program
Let us begin with a simple example of a C+ program that prints a string on the screen.
Program 1.1 (Printing a string).
#include<iostream> // include header file
using manespace std;
int main()
{
cout << "C++ is better that C.\n"; // C++ Statement
return 0;
} // End of example
The simple program demonstrates several C++ features.
1.5.1.1 Program Features
Like C, the C++ program is a collection of functions. The above example contains 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 exceptions, the compiler ignores carriage returns and white spaces, Like C the C++ statements terminate with semicolons.
1.5.2 C++ Comments
C++ introduces a new comment symbol //(double slash). Comments start with a double slash symbol and terminate at the end of line. A comment may start any where in the line and what ever follows till the end of line is ignored. Note that there is no closing symbol.
The double slash comment is basically a single line comment. Multi line comments can be written as follows:
// This is an example of
// C++ program
// Some of its features
The C comment symbols /* , */
are still valid and more suitable for multi line comments.
/*
this is an example of C++ program */
.
/* This is an example of
C++ program
Some of its features
*/
We can use either or both styles in our programs. However, remember that we can not insert //
style comment within the text off a program line. For example, the double slash comment cannot be used in the manner as shown below
for (j=0; j<n; /* loops n times */ j++)
1.5.3 Output Operator
The statement
cout << "C++ is better that C.\n";
displayed the string with in quotes on the screen. The identifier cout
can be used to display individual characters, strings and even numbers. It is a predefined object that corresponds to the standard output stream. Stream just refers to a flow of data and the standard Output stream normally flows to the screen display. The cout
object, whose properties are defined in iostream.h
represents that stream.
The operator <<
is called the insertion operator or put to
operator directs the information on its right to the object on its left.
1.5.4 Return Statement
In C++ main( )
returns an integer type value to the operating system. Therefore every main( )
in C++ should end with a return (0)
statement, otherwise a warning or an error might occur.
1.5.5 Namespace
Namespace
is a new concept introduced by the ANSI C++ standards committee. This defines a scope for the identifiers that are used in a program. For using the identifiers defined in the namespace scope we must include the using directive, like
using namespace std;
Here, std
is the namespace where ANSI C++ standard class libraries are defined. All ANSI C++ programs must include this directive. This will bring all the identifiers defined in std
to the current global scope, using and namespace are the new keywords of C++.
1.5.6 Structure of a Program
Probably the best way to start learning a programming language is by writing a program.
// my first program in C++
#include <iostream>
using namespace std;
int main ()
{
cout << "Hello World!";
return 0;
}
Output would be
Hello World!
The first panel shows the source code for our first program. The second one shows the result of the program once compiled and executed. The way to edit and compile a program depends on the compiler you are using. Depending on whether it has a Development Interface or not and on its version. Consult the compilers section and the manual or help included with your compiler if you have doubts on how to compile a C++ console program.
The previous program is the typical program that programmer apprentices write for the first time, and its result is the printing on screen of the Hello World!
sentence. It is one of the simplest programs that can be written in C++, but it already contains the fundamental components that every C++ program has.
We are going to look line by line at the code we have just written:
// my first program in C++
This is a comment line. All lines beginning with two slash signs (//)
are considered comments and do not have any effect on the behaviour of the program. The programmer can use them to include short explanations or observations within the source code itself. In this case, the line is a brief description of what our program is
#include <iostream>
Lines beginning with a hash sign (#)
are directives for the preprocessor. They are not regular code lines with expressions but indications for the compiler’s preprocessor. In this case the directive
#include<iostream>
tells the preprocessor to include the iostream
standard file. This specific file (iostream) includes the declarations of the basic standard input-output library in C++, and it is included because its functionality is going to be used later in the program.
using namespace std;
All the elements of the standard C++ library are declared within what is called a namespace
, the namespace
with the name std
. So in order to access its functionality we declare with this expression that we will be using these entities. This line is very frequent in C++ programs that use the standard library, and in fact it will be included in most of the source codes included in these tutorials.
int main ()
This line corresponds to the beginning of the definition of the main function. The main function is the point by where all C++ programs start their execution, independently of its location within the source code. It does not matter whether there are other functions with other names defined before or after it – the instructions contained within this function’s definition will always be the first ones to be executed in any C++ program. For that same reason, it is essential that all C++ programs have a main function.
The word main is followed in the code by a pair of parentheses ()
. That is because it is a function declaration: In C++, what differentiates a function declaration from other types of expressions are these parentheses that follow its name. Optionally, these parentheses may enclose a list of parameters within them.
Right after these parentheses we can find the body of the main function enclosed in braces {}
. What is contained within these braces is what the function does when it is executed.
cout << "Hello World!";
This line is a C++ statement. A statement is a simple or compound expression that can actually produce some effect. In fact, this statement performs the only action that generates a visible effect in our first program.
cout
represents the standard output stream in C++, and the meaning of the entire statement is to insert a sequence of characters (in this case the Hello World sequence of characters) into the standard output stream (which usually is the screen).
cout
is declared in the iostream
standard file within the std namespace
, so that’s why we needed to include that specific file and to declare that we were going to use this specific namespace
earlier in our code.
Notice that the statement ends with a semicolon character ;
. This character is used to mark the end of the statement and in fact it must be included at the end of all expression statements in all C++ programs (one of the most common syntax errors is indeed to forget to include some semicolon after a statement).
return 0;
The return statement causes the main function to finish. return may be followed by a return code (in our example is followed by the return code 0). A return code of 0 for the main function is generally interpreted as the program worked as expected without any errors during its execution.
This is the most usual way to end a C++ console program.
The program has been structured in different lines in order to be more readable, but in C++, we do not have strict rules on how to separate instructions in different lines.
Let us consider a slightly more complex C++ program. Assume that we would like to read two numbers from the keyboard and display their average on the screen.
Program 1.2.
#include <iostream>
using namespace std;
int main()
{
float number1, number2, sum, average;
cout <<"Enter two numbers : "; // prompt
cin >> number1; // read numbers
cin >> number2;
sum=number1+number2;
average=sum/2;
cout << "Sum = " << sum << "\n";
cout << "Average =" << average << "\n";
return 0;
}
The output would be
Enter two numbers: 6.5 7.5
Sum = 14
Average = 7
1.5.7 Input Operator
The statement
cin >> number1;
is an input statement and causes. The program to wait for the user to type in a number. The number keyed in is placed in the variable number1
. The identifier cin
is a predefined object in C++ that corresponds to the standard input stream. Here this stream represents the key board.
The operator >>
is known as get from operator. It extracts value from the keyboard and assigns it to the variable on its right.
1.5.8 Variables
The program uses four variables numberl, number2, sum, and average. They are declared as type float by the statement.
float numberl, number2, sum, average;
All variables must be declared before they are used in the program.
1.5.9 Cascading of I/O Operators
We have used the insertion operator <<
repeatedly in the last two statements for printing results, The statement
cout << "Sum = " << sum << "\n";
first sends the string Sum = to cout and then sends the value of sum, Finally, it sends the newline character so that the next output will be in the new line.
The multiple use of <<
in one statement is called cascading. When cascading an output operator, we should ensure necessary blank spaces between different items. Using the cascading technique, the last two statements can be combined as follows:
cout << "Sum = " << sum << "\n";
<< "Average = " << average << "\n";
This is one statement but provides two lines of output. If you want only one line of output, the statement will be:
cout << "Sum = " << sum << ","
<< "Average = " << average << "\n";
The output will be:
Sum = 14, Average = 7
We can also cascade input operator >>
as shown below
cin >> number1 >> number2;
The values are assigned from left to right. That is, if we key two values, say, 10 and 20, then 10 will be assigned to numberl and 20 to number2.
1.5.10 Structure of C++ Program with Class
A typical C++ program would contain four sections. These sections may be placed in separate code files and then compiled independently or jointly.
Include files
Class declaration
Class functions, definition
Main function program
Program 1.3.
# include<iostream.h>
class person
{
char name[30]; int age;
public:
void getdata(void); void display(void);
};
void person :: getdata ( void )
{
cout<<"enter name";
cin>>name;
cout<<"enter age";
cin>>age;
}
void display()
{
cout<<"\n name:"<<name;
cout<<"\n age:"<<age;
}
int main( )
{
person p;
p.getdata();
p.display(); return(0);
}
The output would be
Enter Name : Mr. Abcde
Enter Age : 123
Enter Name : Mr. Abcde
Enter Age : 123
1.5.11 Compiling
Turbo C++ and Borland C++ provide an integrated program development environment under MS DOS, They provide a built-in editor and a menu bar which includes options such as File, Edit. Compile and Run.
We can create and save the source files under the File option, and edit them under the Edit option. We can then compile the program under the Compile option and execute it under the Run option. The Run option can be used without compiling the source code. In this case, the RUN command causes the system to compile, link and run the program in one step. Turbo C++ being the most popular compiler, creation and execution of programs.
1.6 Tokens
The smallest individual units in program are known as tokens. C++ has the following tokens.
Keywords
Identifiers
Constants
Strings
Operators
A C++ program is written using these tokens, white spaces, and the syntax ofthe language. Most of the C++ tokens are basically similar to the C tokens with the exception of some additions and minor modifications.
1.7 Keywords
The keywords implement specific C++ language feature. They are explicitly reserved identifiers and can’t be used as names for the program variables or other user defined program elements.
asm | double | new | switch |
auto | else | operator | template |
break | enum | private | this |
case | extern | protected | throw |
catch | float | public | try |
char | for | register | typedef |
class | friend | return | union |
const | goto | short | unsigned |
continue | if | signed | virtual |
default | inline | sizeof | void |
delete | int | static | volatile |
do | long | struct | while |
1.8 Identifiers and Constants
Identifiers refers to the name of variable, functions, array, class etc. created by programmer. Each language has its own rule for naming the identifiers.
The following rules are common for both C and C++.
Only alphabetic chars, digits and under score are permitted.
The name can’t start with a digit.
Upper case and lower case letters are distinct.
A declared keyword can’t be used as a variable name.
In ANSI C the maximum length of a variable is 32 chars but in C++ there is no bar.
Constants refer to fixed values that do dot change during the execution of a program.
Like C, C++ supports several kinds of literal constants. They include integers n characters, floating point numbers and strings. Liberal constant do not have memory locations, Examples;
123 | // decimal integer |
12.34 | // floating point integer |
037 | // octal integer |
OX2 | // hexadecimal integer |
"C++" | // String constant |
’A’ | // character constant |
L’ab’ | // wide-character constant |
The wchar_t
type is a wide-character literal introduced by ANSI C++ and is intended for character sets that cannot fit a character into a single byte. Wide-character Literals begin with the letter L.
1.9 Basic Data Types
Date types in C++ can be classified under various categories as shown in below.
Both C and C++ compilers support all the built in types. With the exception of void the basic data types may have several modifiers preceding them to serve the needs of various situations. The modifiers signed, unsigned, long and short may applied to character and integer basic data types. However the modifier long may also be applied to double.
Data types in C++ can be classified under various categories.
TYPE | BYTES | RANGE |
---|---|---|
char | 1 | -128 to – 127 |
usigned | 1 | 0 to 265 |
sgned char | 1 | -128 to 127 |
int | 2 | -32768 to 32768 |
unsigned int | 2 | 0 to 65535 |
singed int | 2 | -32768 to 32768 |
short int | 2 | -32768 to 32768 |
long int | 4 | -2147483648 to 2147483648 |
signed long int | 4 | -2147483648 to 2147483648 |
unsigned long int | 4 | 0 to 4294967295 |
float | 4 | 3.4E-38 to 3.4E+38 |
double | 8 | 1.7E -308 to 1.7E +308 |
long double | 10 | 3.4E-4932 to 1.1E+ 4932 |
The type void normally used for:
To specify the return type of function when it is not returning any value.
To indicate an empty argument list to a function.
Example:
void function(void);
Another interesting use of void is in the declaration of genetic pointer Example:
void *gp;
Assigning any pointer type to a void pointer without using a cast is allowed in both C and ANSI C. In ANSI C we can also assign a void pointer to a non-void pointer without using a cast to non void pointer type. This is not allowed in C++. Example:
void *ptr1;
void *ptr2;
Are valid statement in ANSI C but not in C++. We need to use a cast operator.
ptr2=(char*) ptr1;
1.10 User Defined Sate Types
1.10.1 Structures and Classes
We have used user defined data types such as struct and union in C. While these more features have been added to make them suitable for object oriented programming.
The general format of a structure definition is as follows
struct name
{
data_type member1;
data_type member2;
.................
.................
};
Let us take example of a book which has several attributes such as title, number of pages, price etc,. Book structures shown in below.
sruct book
{
chartitle[25];
charauthor[25];
int pages;
float price;
};
struct book, book1, book2, book3;
Here book1, book2, book3 are declared as variables of the user-defined type book.
C++ also permits us to define another user defined data type known as class which can be used just like any other basic data type to declare a variable. The class variables are known as objects, which are the central focus of oops.
1.10.2 Enumerated Data Type
An enumerated data type is another user defined type which provides a way for attaching names to number, these by increasing comprehensibility of the code. The enum keyword automatically enumerates a list of words by assigning them values 0,1,2 and soon. This facility provides an alternative means for creating symbolic. Example:
enum shape {circle,square,triangle};
enum colour {red,blue,green,yellow};
enum position {off,on};
The enumerated data types differ slightly in C++ when compared with ANSI C. In C++, the tag names shape, colour, and position become new type names. That means we can declare new variables using the tag names. Example:
Shape ellipse; // ellipse is of type shape
colour background; // back ground is of type colour
ANSI C defines the types of enums to be ints. In C++, each enumerated data type retains its own separate type. This means that C++ does not allow an int value to be automatically converted to an enum. Example:
colour background =blue; //allowed
colour background =7; //error in c++
colour background =(colour) 7;//ok
How ever an enumerated value can be used in place of an int value. Example:
int c=red ; //valid, colour type promoted to int
By default, the enumerators are assigned integer values starting with 0 for the first enumerator, 1 for the second and so on. We can also write
enum color {red, blue=4,green=8};
enum color {red=5,blue,green};
C++ also permits the creation of anonymous enums ( i.e, enums without tag names) Example:
enum{off,on};
Here off is 0 and on is 1. These constants may be referenced in the same manner as regular constants. Example:
int switch-1=off;
int switch-2=on;
ANSI C permits an enum defined with in a structure or a class, but the enum is globally visible. In C++ an enum defined with in a class is local to that class.
1.11 Symbolic Constants
There are two ways of creating symbolic constants in C++.
using the qualifier const.
defining a set of integer constants using enum keywords.
In both C and C++, any value declared as const can’t be modified by the program in any way. In C++, we can use const in a constant expression. Such as
const int size = 10 ;
char name (size) ;
This would be illegal in C. const allows us to create typed constants instead of having to use #define
to create constants that have no type information.
As with long and short , if we use const modifier alone, it defaults to int. For example,
const size=10;
Means
const int size =10;
C++ requires a const to be initialized. ANSI C does not require an initializer, if none is given, it initializes the const to 0.
In C++ const values are local and in ANSI C const values are global. However they can be made local made local by declaring them as static .In C++ if we want to make const value as global then declare as extern storage class. Example,
extern const total=100;
Another method of naming integer constants is as follows:
enum {X,Y,Z};
This defines X, Y and Z as integer constants with values 0, l and 2 respectively. This is equivalent to:
const X= 0;
const Y =1;
const Z =2;
We can also assign values to X, Y, and Z explicitly. Example:
enum{X=100, Y=50, Z=200};
1.12 Operators in C++
C++ has a rich set of operators. All C operators are valid in C++ also. In addition. C++ introduces some new operators.
<< |
insertion operator |
>> |
extraction operator |
: : | scope resolution operator |
: :* | pointer to member declarator |
* | pointer to member operator |
.* | pointer to member operator |
Delete | memory release operator |
Endl | line feed operator |
New | memory allocation operator |
Setw | field width operator |
In addition, C++ also allows us to provide new definitions to some of the built-in operators. That is, we can give several meanings to an operator, depending upon the types of arguments used. This process is known as operator overloading.
1.12.1 Scope Resolution Operator
Like; C , C++- is also a block structured language. Blocks and scopes can be used in constructing programs. We know that the same variable name can be used to have different meanings in different blocks, The scope of the variable extends from the point of its declaration till the end of the block containing the declaration, A variable declared inside a block is said to be local to that block. Consider the following segment of a program:
...............
...............
{
int x=10;
.........
.........
}
.........
.........
{
int x =1;
.........
.........
}
The two declarations of x refer to two different memory locations containing different values. Statements in the second block cannot refer to the variable x declared in the first block, and vice versa. Blocks in C++ are often nested. For example, the following style is common:
Block2 contained in block l. Note that declaration in an inner block hides a declaration of the same variable in an outer block and therefore each declaration of x causes it to refer to a different data object. With in the inner block the variable x will refer to the data object declared therein.
In C,the global version of a variable can’t be accessed from with in the inner block. C++ resolves this problem by introducing a new operator :: called the scope resolution operator. This can be used to uncover a hidden variable.
: : variable-name
The next program illustrates this feature.
Program 1.4 (Scope Resolution Operator).
#include <iostream>
using namespace std;
// declare global variable
int num = 50;
int main ()
{
// declare local variable
int num = 100;
// print the value of the variables
cout << " The value of the local variable num: " << num;
// use scope resolution operator (::) to access the global variable
cout << "\n The value of the global variable num: " << ::num;
return 0;
}
The output would be
The value of the local variable num: 100
The value of the global variable num: 50
1.12.2 Member Dereferencing Operator
As you know, C++ permits us to define a class containing various types of data and functions as members, C++ also permits us to access the class members, through pointers. In order to achieve this, C++ provides a set of three pointer-to-member operators. The following shows the operators and their functions.
::* | To declare a pointer to a member of a class |
* | To access a member using object name and a pointer to that matter |
->* |
To access a member using a pointer to the object and a pointer to that member. |
1.12.3 Memory Management Operator
C uses malloc()
and calloc
functions to allocate memory dynamically at run time. Similarly it uses the functions free( )
to free dynamically allocated memory. We use dynamic allocation techniques when it is not known in advance how much of memory space as needed.
C++ also support those functions it also defines two unary operators new
and delete
that perform the task of allocating and freeing the memory in a better and easier way.
An object can be created by using new
and destroyed by using delete
.
The new
operator can be used to create objects of any type.
pointer-variable = new datatype;
Here pointer-variable is a pointer of type datatype. The new operator allocates sufficient memory to hold a data object of type datatype. Example
p=new int;
q=new int;
Where p is a pointer of type int and q is a pointer of type float. Alternatively, we can combine the declaration of pointers and their assignments as follows
int *p=new int;
float *p=new float;
Subsequently, the statements
*p=25;
*q=7.5;
Assign 25 to the newly created int object and 7.5 to the float object.We can also initialize the memory using the new operator.
int *p= new int(25);
float *q =new float(7.5);
new can be used to create a memory space for any data type including user defined such as arrays, structures and classes. The general form for a one-dimensional array is:
pointer-variable = new data types [size];
For example, the statement
int *p = new int[10];
creates a memory space for an array of 10 integers. p[0] will refer to the first element, p[1] to the second element and so on.
If a data object is no longer needed, it is destroyed to release the memory space for reuse.
delete pointer-variable;
Example:
delete p;
delete q;
If we want to free a dynamically allocated array, we must use the following form of delete.
delete [size] pointer-variable;
or
delete [ ] pointer variable;
will delete the entire array pointed to by p.
Program 1.5.
#include <iostream>
using namespace std ;
int main()
{
int size; // variable declaration
int *arr = new int[size]; // creating an array
cout<<"Enter the size of the array : ";
std::cin >> size; //
cout<<"\nEnter the element : ";
for(int i=0;i<size;i++) // for loop
{
cin>>arr[i];
}
cout<<"\nThe elements that you have entered are :";
for(int i=0;i<size;i++) // for loop
{
cout<<arr[i]<<",";
}
delete arr; // deleting an existing array.
return 0;
}
The output would be
/tmp/mGG0pbv2tb.o
Enter the size of the array : 3
Enter the element : 1
2
3
The elements that you have entered are :1,2,3,
1.12.4 Manipulators
Manipulators are operator that are used to format the data display. The most commonly manipulators are endl and setw.
The endl manipulator, when used in an output statement, causes a linefeed to be inserted, same effect as using the new line character "/n".
setw function stands for set width. This manipulator is used to specify the minimum number of character positions on the output field a variable will consume.
This manipulator is declared in header file <iomanip>.
The manipulator setw(5) specifies a field with 5 for printing the value of the variable. This is right justified as shown in below.
Program 1.6 (Use of Manipulators).
#include <iostream>
#include <iomainp> // for setw
using namespace std;
int main()
{
int Basic =650, Allowance=95, Total = 1045;
cout << "setw(10)" << "Basic"<< setw(10) << Basic << endl
<< "setw(10)" << "Allowance"< setw(10) << Allowance << endl
<< "setw(10)" << "Total"<< setw(10) << Total << endl;
return 0;
}
The output would be
Basic 650
Allowance 95
Total 1045
1.12.5 Type Cast Operator
Traditional C casts arc augmented in C++ by a function-call notation as a syntactic alternative. The following two versions are equivalent:
(type- name)expression // C notation
type-name (expression) // C++ notation
Examples:
average = sum/(float)i; // C notation
average = sum/float(i); // C++ notation
Program 1.7 (Explicit Type Casting).
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
int intvar = 25;
float floatvar=35.87;
cout << "intvar = " << intvar;
cout << "\nfloatvar = " << floatvar;
cout << "\nfloat(intvar) =" <<float(intvar);
cout << "\nint(floatvar) = "<< int(floatvar);
getch();
}
The output would be
intvar = 25
floatvar = 35.87
float(intvar) =25
int(floatvar) = 35
1.13 Expression and Their Types
C++ expression consists of operators, constants, and variables which are arranged according to the rules of the language. It can also contain function calls which return values. An expression can consist of one or more operands, zero or more operators to compute a value. Every expression produces some value which is assigned to the variable with the help of an assignment operator.
An expression can be of following types:
Constant expressions
Integral expressions
Float expressions
Pointer expressions
Relational expressions
Logical expressions
Bitwise expressions
Special assignment expressions
If the expression is a combination of the above expressions, such expressions are known as compound expressions.
1.13.1 Constant Expression
A constant expression is an expression that consists of only constant values. Example
#include <iostream>
using namespace std;
int main()
{
int x; // variable declaration.
x=(3/2) + 2; // constant expression
cout<<"Value of x is : "<<x; // displaying the value of x.
return 0;
}
The output would be
Value of x is : 3
1.13.2 Integral Expressions
An integral expression is an expression that produces the integer value as output after performing all the explicit and implicit conversions.Example
#include <iostream>
using namespace std;
int main()
{
int x; // variable declaration.
int y; // variable declaration
int z; // variable declaration
cout<<"Enter the values of x and y";
cin>>x>>y;
z=x+y;
cout<<"\n"<<"Value of z is :"<<z; // displaying the value of z.
return 0;
}
The output would be
Enter the values of x and y
8.5
9
Value of z is :17
1.13.3 Float Expressions
A float expression is an expression that produces floating-point value as output after performing all the explicit and implicit conversions. Example
#include <iostream>
using namespace std;
int main()
{
float x=8.9; // variable initialization
float y=5.6; // variable initialization
float z; // variable declaration
z=x+y;
std::cout <<"value of z is :" << z<<std::endl; // displaying the value of z.
return 0;
}
The output would be
value of z is :14.5
1.13.4 Pointer Expressions
A pointer expression is an expression that produces address value as an output. Example
#include <iostream>
using namespace std;
int main()
{
int a[]={1,2,3,4,5}; // array initialization
int *ptr; // pointer declaration
ptr=a; // assigning base address of array to the pointer ptr
ptr=ptr+1; // incrementing the value of pointer
std::cout <<"value of second element of an array : " << *ptr<<std::endl;
return 0;
}
The output would be
value of second element of an array : 2
1.13.5 Relational Expressions
A relational expression is an expression that produces a value of type bool, which can be either true or false. It is also known as a boolean expression. When arithmetic expressions are used on both sides of the relational operator, arithmetic expressions are evaluated first, and then their results are compared. Example
#include <iostream>
using namespace std;
int main()
{
int a=45; // variable declaration
int b=78; // variable declaration
bool y= a>b; // relational expression
cout<<"Value of y is :"<<y; // displaying the value of y.
return 0;
}
The output would be
Value of y is :0
1.13.6 Logical Expressions
A logical expression is an expression that combines two or more relational expressions and produces a bool type value. The logical operators are &&
and
| | that combines two or more relational expressions. Example
#include <iostream>
using namespace std;
int main()
{
int a=2;
int b=7;
int c=4;
cout<<((a>b)||(a>c));
return 0;
}
The output would be
0
1.13.7 Bitwise Expressions
A bitwise expression is an expression which is used to manipulate the data at a bit level. They are basically used to shift the bits.
#include <iostream>
using namespace std;
int main()
{
int x=5; // variable declaration
std::cout << (x>>1) << std::endl;
return 0;
}
The output would be
2
1.13.8 Special Assignment Expressions
Special assignment expressions are the expressions which can be further classified depending upon the value assigned to the variable.
1.13.8.1 Chained Assignment
Chained assignment expression is an expression in which the same value is assigned to more than one variable by using single statement.
#include <iostream>
using namespace std;
int main()
int a; // variable declaration
int b; // variable declaration
a=b=80; // chained assignment
std::cout <<"Values of 'a' and 'b' are : " <<a<<","<<b<< std::endl;
return 0;
}
The output would be
Values of 'a' and 'b' are : 80,80
1.13.8.2 Embedded Assignment Expression
An embedded assignment expression is an assignment expression in which assignment expression is enclosed within another assignment expression.
#include <iostream>
using namespace std;
int main()
{
int a; // variable declaration
int b; // variable declaration
a=10+(b=90); // embedded assignment expression
std::cout <<"Values of 'a' is " <<a<< std::endl;
return 0;
}
The output would be
Values of 'a' is 100
1.13.8.3 Compound Assignment
A compound assignment expression is an expression which is a combination of an assignment operator and binary operator.
#include <iostream>
using namespace std;
int main()
{
int a=10; // variable declaration
a+=10; // compound assignment
std::cout << "Value of a is :" <<a<< std::endl; // displaying the value of a.
return 0;
}
The output would be
Value of a is :20
1.14 Control Structures
In C++, a large number of functions are used that pass messages, and process the data contained in objects. A function is set up to perform a task of any combination of the following three control structures.
Sequence structure (Straight line)
Selection structure (branching)
Loop structure (iteration or repetition)
1.14.1 The if statement
In C++ programming, if statement is used to test the condition. There are various types of if statements in C++.
if statement
if-else statement
1.14.1.1 if statement
The C++ if statement tests the condition. It is executed if condition is true. Example
#include <iostream>
using namespace std;
int main () {
int num = 10;
if (num % 2 == 0)
{
cout<<"It is even number";
}
return 0;
}
The output would be
It is even number
1.14.1.2 if-else statement
The C++ if-else statement also tests the condition. It executes if block if condition is true otherwise else block is executed. Example
#include <iostream>
using namespace std;
int main () {
int num = 11;
if (num % 2 == 0)
{
cout<<"It is even number";
}
else
{
cout<<"It is odd number";
}
return 0;
}
The output would be
It is odd number
1.14.1.3 Program with user input value
#include <iostream>
using namespace std;
int main () {
int num;
cout<<"Enter a number to check grade:";
cin>>num;
if (num <0 || num >100)
{
cout<<"wrong number";
}
else if(num >= 0 && num < 50){
cout<<"Fail";
}
else if (num >= 50 && num < 60)
{
cout<<"D Grade";
}
else if (num >= 60 && num < 70)
{
cout<<"C Grade";
}
else if (num >= 70 && num < 80)
{
cout<<"B Grade";
}
else if (num >= 80 && num < 90)
{
cout<<"A Grade";
}
else if (num >= 90 && num <= 100)
{
cout<<"A+ Grade";
}
}
The output would be
Enter a number to check grade:66
C Grade
1.14.2 C++ switch
The C++ switch statement executes one statement from multiple conditions. It is like if-else-if ladder statement in C++. Example
#include <iostream>
using namespace std;
int main () {
int num;
cout<<"Enter a number to check grade:";
cin>>num;
switch (num)
{
case 10: cout<<"It is 10"; break;
case 20: cout<<"It is 20"; break;
case 30: cout<<"It is 30"; break;
default: cout<<"Not 10, 20 or 30"; break;
}
}
The output would be
Enter a number:
10
It is 10
1.14.3 do - while loop
The C++ do-while loop is used to iterate a part of the program several times. If the number of iteration is not fixed and you must have to execute the loop at least once, it is recommended to use do-while loop. Example
#include <iostream>
using namespace std;
int main() {
int i = 1;
do{
cout<<i<<"\n";
i++;
} while (i <= 10) ;
}
The output would be
1
2
3
4
5
6
7
8
9
10
1.14.4 While loop
In C++, while loop is used to iterate a part of the program several times. If the number of iteration is not fixed, it is recommended to use while loop than for loop. Example
#include <iostream>
using namespace std;
int main() {
int i=1;
while(i<=10)
{
cout<<i <<"\n";
i++;
}
}
The output would be
1
2
3
4
5
6
7
8
9
10
1.14.5 for statement
The C++ for loop is used to iterate a part of the program several times. If the number of iteration is fixed, it is recommended to use for loop than while or do-while loops. Example
#include <iostream>
using namespace std;
int main() {
for(int i=1;i<=10;i++){
cout<<i <<"\n";
}
}
The output would be
1
2
3
4
5
6
7
8
9
10
2 Functions
2.1 The main( ) Function
ANSI C does not specify any return type for the main ( )
function which is the starting point for the execution of a program. The definition of main( )
is :-
main()
{
//main program statements
}
This is property valid because the main ()
in ANSI C does not return any value. In C++, the main ()
returns a value of type int to the operating system. The functions that have a return value should use the return statement for terminating. The main ()
function in C++ is therefore defined as follows.
int main( )
{
.............
.............
return(0);
}
Since the return type of functions is int by default, the key word int in the main( )
header is optional.
2.2 Function Prototyping
Function prototyping is one of the major improvements added to C++ functions. The prototype describes the function interface to the compiler by giving details such as the number and type of arguments and the type of return values. With function prototyping a template is always used when declaring and defining a function.
When a function is called, the compiler uses the template to ensure that proper arguments are passed, and the return value is treated correctly. Any violation in matching the arguments or the return types will be caught by the compiler at the time of compilation itself. These checks and controls did not exist in the conventional C functions.
While C++ makes the prototyping essential, ANSI C makes it optional, perhaps, to preserve the compatibility with classic C.
Function prototype is a declaration statement in the calling program and is of the following form:
type function-name(argument list);
Example:
float volume(int x, float y, float z);
Note that each argument variable must be declared independently in the parentheses.
float volume(int x, float y, z);
is illegal.
Program 2.1 (Function Prototyping).
#include<iostream>
using namespace std;
// function prototype
void multiply(int, int);
int main() {
// calling the function before declaration.
multiply(50, 20);
return 0;
}
// defining function
void multiply(int x, int y)
{
cout << "The product of two numbers " << x << " and " << y << " is " << (x*y);
}
The output would be
The product of two numbers 50 and 20 is 1000
2.3 Call by Reference
The call by reference method of passing arguments to a function copies the reference of an argument into the formal parameter. Inside the function, the reference is used to access the actual argument used in the call. This means that changes made to the parameter affect the passed argument.
To pass the value by reference, argument reference is passed to the functions just like any other value. So accordingly you need to declare the function parameters as reference types as in the following function swap()
, which exchanges the values of the two integer variables pointed to by its arguments. Consider the following function
void swap(int &a, int &b) /* a and b are reference variables */
{
int t =a ; /* save the value at address a to t */
a = b; /* put b into a */
b = t; /* put t into b */
}
Now if m and n are two integer variables, then the function call
swap(m,n)
will exchange the values of m and n using their reference variables a and b.
Program 2.2 (Call by Reference).
#include<iostream>
using namespace std;
void swap(int *x, int *y)
{
int swap;
swap=*x;
*x=*y;
*y=swap;
}
int main()
{
int x=500, y=100;
swap(&x, &y); // passing value to function
cout<<"Value of x is: "<<x<<endl;
cout<<"Value of y is: "<<y<<endl;
return 0;
}
The output would be
Value of x is: 100
Value of y is: 500
2.4 Return by reference
It is very different from Call by reference. Functions behaves a very important role when variable or pointers are returned as reference.
Below is the code to illustrate the Return by reference.
Program 2.3 (Return by Reference).
#include<iostream>
#include<conio.h>
using namespace std;
int & max(int &x, int &y);
int main() {
//Works a as Return By Reference Function
int a = 50, b = 49;
max(a,b) = 1000;
cout << "\nValues a :"<<a<<" b:"<<b;
}
// Return By Reference Function
int & max(int &x, int &y) {
if(x > y)
return x;
return y;
}
The output would be
Values a :1000 b:49
2.5 Inline functions
The main use of the inline function in C++ is to save memory space. Whenever the function is called, then it takes a lot of time to execute the tasks, such as moving to the calling function. If the length of the function is small, then the substantial amount of execution time is spent in such overheads, and sometimes time taken required for moving to the calling function will be greater than the time taken required to execute that function.
The solution to this problem is to use macro definitions known as macros. The preprocessor macros are widely used in C, but the major drawback with the macros is that these are not normal functions which means the error checking process will not be done during the compilation.
C++ has provided one solution to this problem. In the case of function calling, the time for calling such small functions is huge, so to overcome such a problem, a new concept was introduced known as an inline function. When the function is encountered inside the main() method, it is expanded with its definition thus saving time.
Syntax for an inline function:
inline function-header
{
// function code
}
We cannot provide the inlining to the functions in the following circumstances:
If a function is recursive.
If a function contains a loop like for, while, do-while loop.
If a function contains static variables.
If a function contains a switch or go to statement
When do we require an inline function?
An inline function can be used in the following scenarios:
An inline function can be used when the performance is required.
It can be used over the macros.
We can use the inline function outside the class so that we can hide the internal implementation of the function.
Let’s understand through an example.
Program 2.4 (Inline functions).
#include <iostream>
using namespace std;
inline int add(int x, int y)
{
return(x+y);
}
int main() {
int x, y;
cout << "Enter the value of x : ";
cin >> x;
cout << "Enter the value of y: ";
cin >> y;
cout<<"Addition of "<< x << " and " << y << " is : " <<add(x,y);
}
The output would be
Enter the value of x : 4
Enter the value of y: 9
Addition of 4 and 9 is : 13
2.6 Default Arguments
C++ allows us to call a function with out specifying all its arguments.In such cases, the function assigns a default value to the parameter which does not have a matching arguments in the function call. Default values are specified when the function is declared .The compiler looks at the prototype to see how many arguments a function uses and alerts the program for possible default values.
float amount (float principle,int period, float rate=0.15);
The default value is specified in a manner syntactically similar to a variable initialization. The above prototype declares a default value of 0.15 to the argument rate. A subsequent function call like
value=amount(5000,7); //one argument missing
passes the value of 5000 to principle and 7 to period and then lets the function, use default value of 0.15 for rate. The call:
value=amount(5000,5,0.12); //no missing argument
passes an explicit value of 0.12 rate.
One important point to note is that only the trailing arguments can have default values. That is, we must add default from right to left. We cannot provide a default to a particular argument in the middle of an argument list.
int mul(int i, int j=5,int k=10);//legal
int mul(int i=0,int j,int k=10);//illegal
int mul(int i=5,int j);//illegal
int mul(int i=2,int j=5,int k=10);//legal
Default arguments are useful in situation whose some arguments always have the some value. For example,bank interest may retain the same for all customers for a particular period of deposit.
Program 2.5 (Default Arguments).
#include<iostream>
using namespace std;
int sum(int x, int y, int z=0, int w=0) // Here there are two values in the default arguments
{ // Both z and w are initialised to zero
return (x + y + z + w); // return sum of all parameter values
}
int main()
{
cout << sum(10, 15) << endl; // x = 10, y = 15, z = 0, w = 0
cout << sum(10, 15, 25) << endl; // x = 10, y = 15, z = 25, w = 0
cout << sum(10, 15, 25, 30) << endl; // x = 10, y = 15, z = 25, w = 30
return 0;
}
The output would be
25
50
80
Advantage of providing the default arguments are:
We can use default arguments to add new parameters to the existing functions.
Default argument s can be used to combine similar functions into one.
2.7 const Arguments
We can declare the function arguments as the constant argument using the const keyword. And if the value of function arguments is declared const, it does not allow changing its value. Syntax
int strlen (const char *p)
int length (const string &s)
The fun_name()
function contains a const argument whose value can never be changed once it defines in the program.
Program 2.6 (cost arguments).
#include <iostream>
using namespace std;
// create an integer Test() function contains an argument num
int Test (const int num)
{
// if we change the value of the const argument, it thwrows an error.
// num = num + 10;
cout << " The value of num: " << num << endl;
return 0;
}
int main ()
{
// call function
Test(5);
}
The output would be
The value of num: 5
2.8 Function Overloading
If we create two or more members having the same name but different in number or type of parameter, it is known as C++ overloading.
Types of overloading in C++ are:
Function overloading
Operator overloading
Function Overloading
Overloading refers to the use of the same thing for different purposes. C++ also permits overloading functions. This means that we can use the same function name to creates functions that perform a variety of different tasks. This is known as function polymorphism in OOPs.
Using the concepts of function overloading, a family of functions with one function name but with different argument lists in the functions call. The correct function to be invoked is determined by checking the number and type of the arguments but not on the function type.
For example an overloaded add()
function handles different types of data as shown below.
//Declaration
int add(int a, int b); //prototype 1
int add (int a, int b, int c); //prototype 2
double add(double x, double y); //prototype 3
double add(double p, double q); //prototype 4
double add(double p, int q); //prototype 5
//function call
cout<<add(5,10); //uses prototype 1
cout<<add(5,10,15); //uses prototype 2
cout<<add(12.5,7.5); //uses prototype 3
cout<<add(15,10.0); //uses prototype 4
cout<<add(0.75,5); //uses prototype 5
A function call first matches the prototype having the same no and type of arguments and then calls the appropriate function for execution. The function selection invokes the following steps:
The compiler first tries to find an exact match in which the types of actual arguments are the same and use that function .
If an exact match is not found the compiler uses the integral promotions to the actual arguments such as :
char to int float to double
to find a match
When either of them tails, the compiler tries to use the built in conversions to the actual arguments and them uses the function whose match is unique. If the conversion is possible to have multiple matches, then the compiler will give error message.
long square (long n); double square(double x);
A function call such as
square(10)
Will cause an error because int argument can be converted to either long or double. There by creating an ambiguous situation as to which version of
square( )
should be used.
Program 2.7 (Function Overloading ).
// Function area() is overloaded three times
#include<iostream>
using namespace std;
//Deceleration of funciton prototypes
int area(int);
int area(int, int);
double area (double);
int main()
{
cout << "Area of the square of 5 unit side is " << area(5)<<"\n";
cout << "Area of the rectangle of 5 unit length and 10 unit breath is " << area(5,10)<<"\n";
cout << "Area of the circle of 5.5 unit radius is " << area(5.5);
return 0;
}
int area(int side) // Area of square
{
return(side*side);
}
int area(int length, int breath) // Area of rectangle
{
return(length*breath);
}
double area(double radius) // Area of circle
{
return(3.14*radius*radius);
}
The output would be
Area of the square of 5 unit side is 25
Area of the rectangle of 5 unit length and 10 unit breath is 50
Area of the circle of 5.5 unit radius is 94.985
2.9 Math Library Functions
C++ offers some basic math functions and the required header file to use these functions is <math.h>
.
2.9.1 Trignometric functions
Method | Description |
---|---|
cos(x) | It computes the cosine of x. |
sin(x) | It computes the sine of x. |
tan(x) | It computes the tangent of x. |
acos(x) | It finds the inverse cosine of x. |
asin(x) | It finds the inverse sine of x. |
atan(x) | It finds the inverse tangent of x. |
atan2(x,y) | It finds the inverse tangent of a coordinate x and y. |
2.9.2 Hyperbolic functions
Method | Description |
---|---|
cosh(x) | It computes the hyperbolic cosine of x. |
sinh(x) | It computes the hyperbolic sine of x. |
tanh(x) | It computes the hyperbolic tangent of x. |
acosh(x) | It finds the arc hyperbolic cosine of x. |
asinh(x) | It finds the arc hyperbolic sine of x. |
atanh(x) | It finds the arc hyperbolic tangent of x. |
2.9.3 Exponential functions
Method | Description |
---|---|
exp(x) | It computes the exponential e raised to the power x. |
log(x) | It computes the natural logarithm of x. |
log10(x) | It computes the common logarithm of x. |
modf() | It breaks a number into an integer and fractional part. |
exp2(x) | It computes the base 2 exponential of x. |
expm1(x) | It computes the exponential raised to the power x minus one. |
log1p(x) | It computes the natural logarithm of x plus one. |
log2(x) | It computes the base 2 logarithm of x. |
logb(x) | It computes the logarithm of x. |
2.9.4 Maximum,Minimum and Difference functions
Method | Description |
---|---|
fdim(x,y) | It calculates the positive difference between x and y. |
fmax(x,y) | It returns the larger number among two numbers x and y. |
fmin() | It returns the smaller number among two numbers x and y . |
2.9.5 Power functions
Method | Description |
---|---|
pow(x,y) | It computes x raised to the power y. |
sqrt(x) | It computes the square root of x. |
cbrt(x) | It computes the cube root of x. |
hypot(x,y) | It finds the hypotenuse of a right angled triangle. |
2.9.6 Nearest integer operations
Method | Description |
---|---|
ceil(x) | It rounds up the value of x. |
floor(x) | It rounds down the value of x. |
round(x) | It rounds off the value of x. |
lround(x) | It rounds off the value of x and cast to long integer. |
llround(x) | It rounds off the value of x and cast to long long integer. |
fmod(n,d) | It computes the remainder of division n/d. |
trunc(x) | It rounds off the value x towards zero. |
rint(x) | It rounds off the value of x using rounding mode. |
lrint(x) | It rounds off the value of x using rounding mode and cast to long integer. |
llrint(x) | It rounds off the value x and cast to long long integer. |
nearbyint(x) | It rounds off the value x to a nearby integral value. |
remainder(n,d) | It computes the remainder of n/d. |
remquo() | It computes remainder and quotient both. |
2.9.7 Other functions
Method | Description |
---|---|
fabs(x) | It computes the absolute value of x. |
abs(x) | It computes the absolute value of x. |
fma(x,y,z) | It computes the expression x*y+z. |
Program 2.8 (Math Library Functions).
#include <iostream>
#include <math.h>
using namespace std;
int main ()
{
int PI = 3.142;
cout<< "cos(60) = " << cos ( 60.0 * PI / 180.0 )<<endl;
cout<< "sin(60) = " << sin ( 60.0 * PI / 180.0 )<<endl;
cout<< "tan(45) = " << tan ( 45.0 * PI / 180.0 )<<endl;
cout<< "acos(0.5) = " << acos (0.5) * 180.0 / PI<<endl;
cout<< "asin(0.5) = " << asin (0.5) * 180.0 / PI<<endl;
cout<< "atan(1.0) = " << atan (1.0) * 180.0 / PI<<endl;
cout<< "2^3 = " << pow(2,3)<<endl;
cout<< "sqrt(49) = " << sqrt(49)<<endl;
cout<< "ceil(3.8) = " << ceil(3.8)<<endl;
cout<< "floor(2.3) = " << floor(2.3)<<endl;
cout<< "fmod(5.3,2) = " << fmod(5.3,2)<<endl;
cout<< "trunc(5.3,2) = " << trunc(2.3)<<endl;
cout<< "round(4.6) = " << round(4.6)<<endl;
cout<< "remainder(18.5,4.2) = " << remainder(18.5 ,4.2)<<endl;
cout<< "fmax(100.0,1.0) = " << fmax(100.0,1.0)<<endl;
cout<< "fmin(100.0,1.0) = " << fmin(100.0,1.0)<<endl;
cout<< "fdim(2.0,1.0) = " << fdim(2.0,1.0)<<endl;
cout<< "fabs(3.1416) = " << fabs(3.1416)<<endl;
cout<< "abs(3.1416) = " << abs(3.1416)<<endl;
cout<< "log(5) = " << log(5)<<endl;
cout<< "exp(5.0) = " << exp(5.0)<<endl;
cout<< "log10(5) = " << log10(5)<<endl;
return 0;
}
The output would be
cos(60) = 0.540302
sin(60) = 0.841471
tan(45) = 0.931596
acos(0.5) = 62.8319
asin(0.5) = 31.4159
atan(1.0) = 47.1239
2^3 = 8
sqrt(49) = 7
ceil(3.8) = 4
floor(2.3) = 2
fmod(5.3,2) = 1.3
trunc(5.3,2) = 2
round(4.6) = 5
remainder(18.5,4.2) = 1.7
fmax(100.0,1.0) = 100
fmin(100.0,1.0) = 1
fdim(2.0,1.0) = 1
fabs(3.1416) = 3.1416
abs(3.1416) = 3.1416
log(5) = 1.60944
exp(5.0) = 148.413
log10(5) = 0.69897
3 Classes and Objects
Class
Class is a group of objects that share common properties and relationships. In C++, a class is a new data type that contains member variables and member functions that operates on the variables. A class is defined with the keyword class. It allows the data to be hidden, if necessary from external use. When we defining a class, we are creating a new abstract data type that can be treated like any other built in data type.
Generally a class specification has two parts
Class declaration
Class function definition
The class declaration describes the type and scope of its members. The class function definition describes how the class functions are implemented.
The general form of class declaration is
class class-name
{
private:
variable declarations;
function declaration ;
public:
variable declarations;
function declaration;
};
The members that have been declared as private can be accessed only from with in the class. On the other hand, public members can be accessed from outside the class also. The data hiding is the key feature of oops. The use of keywords private is optional by default, the members of a class are private.
The variables declared inside the class are known as data members and the functions are known as members mid the functions. Only the member functions can have access to the private data members and private functions. However, the public members can be accessed from the outside the class. The binding of data and functions together into a single class type variable is referred to as encapsulation.
Syntax
class item
{
int member;
float cost;
public;
void getdata (int a, float b);
void putdata (void);
};
The class item contains two data members and two function members, the data members are private by default while both the functions are public by declaration. The function getdata()
can be used to assign values to the member variables member and cost, and putdata()
for displaying their values. These functions provide the only access to the data members from outside the class.
Creating Objects
Once a class has been declared we can create variables of that type by using the class name. Example:
item x; // memory for x is created
creates a variables x of type item. In C++, the class variables are known as objects. Therefore x is called an object of type item.
item x,y,z
also possible.
class item
{
------------
------------
------------
} x,y,z;
would create the objects x,y,z of type item.
Program 3.1 (C++ program with class).
#include <iostream>
using namespace std;
// create a class
class Room {
public:
double length;
double breadth;
double height;
double calculateArea() {
return length * breadth;
}
double calculateVolume() {
return length * breadth * height;
}
};
int main() {
// create object of Room class
Room room1;
// assign values to data members
room1.length = 42.5;
room1.breadth = 30.8;
room1.height = 19.2;
// calculate and display the area and volume of the room
cout << "Area of Room = " << room1.calculateArea() << endl;
cout << "Volume of Room = " << room1.calculateVolume() << endl;
return 0;
}
The output would be
Area of Room = 1309
Volume of Room = 25132.8
3.1 Arrays within a class
Arrays can be declared as the members of a class.
The arrays can be declared as private, public or protected members of the class.
To understand the concept of arrays as members of a class, consider this example.
Program 3.2 (Arrays within a class).
A program to demonstrate the concept of arrays as class members.
#include<iostream>
using namespace std;
const int m=50;
class items
{
int itemcode[m];
float itemPrice[m];
int count;
public:
void CNT()
{
count = 0;
}
void getitem();
void display();
void displaysum();
void remove();
void displayItems();
};
void items :: getitem()
{
cout<<"Enter item code :";
cin>>itemcode[count];
cout<<"Enter item cost :";
cin>>itemPrice[count];
count++;
}
void items :: displaysum()
{
float sum =0;
for(int i=0;i<count;i++)
{
sum = sum+itemPrice[i];
}
cout<<"\nTotal Value :"<<sum<<"\n";;
}
void items :: remove()
{
int a;
cout<<"Enter item code: ";
cin>>a;
for(int i=0;i<count;i++)
if(itemcode[i] == a)
itemPrice[i] = 0;
}
void items :: displayItems()
{
cout<<"\n Code Price\n";
for(int i=0;i<count;i++)
{
cout<<"\n"<<itemcode[i];
cout<<" "<<itemPrice[i];
}
cout<<"\n";
}
int main()
{
items order;
order.CNT();
int x;
do{
cout<<"\n you can do the following:";
cout<<"Enter Appropriate number \n";
cout<<"\n1 : Add an item";
cout<<"\n2 : Display Total Value";
cout<<"\n3 : Delete an item";
cout<<"\n4 : Display all items";
cout<<"\n5 : Quit";
cout<<"\n\n Choice : ";
cin>>x;
switch(x)
{
case 1:
order.getitem();
break;
case 2:
order.displaysum();
break;
case 3:
order.remove();
break;
case 4:
order.displayItems();
break;
case 5:
break;
default:
cout<<"Invalid Output\n" ;
}
}while(x!=5);
}
The output would be
you can do the following:Enter Appropriate number
1 : Add an item
2 : Display Total Value
3 : Delete an item
4 : Display all items
5 : Quit
Choice : 1
Enter item code :111
Enter item cost :100
you can do the following:Enter Appropriate number
1 : Add an item
2 : Display Total Value
3 : Delete an item
4 : Display all items
5 : Quit
Choice : 1
Enter item code :222
Enter item cost :200
you can do the following:Enter Appropriate number
1 : Add an item
2 : Display Total Value
3 : Delete an item
4 : Display all items
5 : Quit
Choice : 1
Enter item code :333
Enter item cost :300
you can do the following:Enter Appropriate number
1 : Add an item
2 : Display Total Value
3 : Delete an item
4 : Display all items
5 : Quit
Choice : 2
Total Value :600
you can do the following:Enter Appropriate number
1 : Add an item
2 : Display Total Value
3 : Delete an item
4 : Display all items
5 : Quit
Choice : 3
Enter item code: 222
you can do the following:Enter Appropriate number
1 : Add an item
2 : Display Total Value
3 : Delete an item
4 : Display all items
5 : Quit
Choice : 4
Code Price
111 100
222 0
333 300
you can do the following:Enter Appropriate number
1 : Add an item
2 : Display Total Value
3 : Delete an item
4 : Display all items
5 : Quit
Choice : 5
The program uses two arrays namely itemCode[]
to hold the code number of items and itemPrice[]
to hold the prices. A third data member count is used to keep a record of items in the list. The program uses a total of four functions to implement the operations to be performed on the list. The statement
const int m >> 50;
defines the size of the array members.
The first function CNT()
simply sets the variable count to zero. The second function getitem()
gets the item code and the item price interactively and assigns them to the array members itemCode[count]
and itemPrice[count]
Note that inside this function count is incremented after the assignment operation is over. The function displaysum()
evaluates the total value of the order and then prints the value. The fourth function remove()
deletes a given item from the list. It uses the item code to locate it in the list and sets the price to zero indicating that the item is not active in the list. Lastly, the function displayitems()
displays all the items in the list.
The program implements all the tasks using a menu-based user interface.
3.2 Memory allocation for objects
We have stated that the memory space for object is allocated when they are declared and not when the class is specified. This statement is only partly true. Basically the member functions are created and placed in the memory space only once when they are defined as a part of a class specification. Since all the objects belonging to that class uses the same member functions, whenever the objects are created no separate space is allocated for member functions. Only space for member variables is allocated separately for each object. Separate memory locations for the objects are essential because the member variable will hold different data values for different object.
3.3 Static data members
A data members of a class can be qualified as static. The properties of a static member variable are similar to that of a C language static variable. A static member variable has certain special characteristics These are
It is initialize to 0(zero) when first object of its class is created. No other initialization is permitted.
Only single copy of that member is created for the entire class and is shared by all the objects of that class, no matter how many objects are created.
it’s visible only within the class, but its lifetime is the entire program
Static variable are normally used to maintain the common values to the entire class. lets see for example a static data member can be used as a counter that records the occurrences of all the objects.
Program 3.3 (Static class member ).
The below program show static data member
#include<iostream>
using namespace std;
class items
{
static int count;
int number;
public:
void getdata(int a)
{
number=a;
count++;
}
void getcount()
{
std::cout<<"count is : "<<count <<"\n";
}
};
int items:: count;
int main()
{
items x,y,z; // count is initialized to zero
x.getcount() ; // display count
y.getcount() ;
z.getcount() ;
x.getdata(100) ; // getting data into object x
y.getdata(200 ) ; // getting data into object y
z.getdata(300) ; // getting data into object z
cout << "After reading data" << "\n";
x.getcount() ; // display count
y.getcount() ;
z.getcount() ;
return 0;
}
The output would be
count is : 0
count is : 0
count is : 0
After reading data
count is : 3
count is : 3
count is : 3
Note that The type and scope of each static member variable must be defined outside the class definition. This is necessary because the static data members are stored separately rather than as a part of an object. Since they are associated with the class itself rather than with any class object, they are also known as class variables.
The static variable count is initialized to zero when the object are created. The count is incremented whenever the data is read into an object. since the data is read into objects three times, the variable count is incremented three times. because there is only one copy of count shared by all the three objects, all the three output statements cause the value 3 to be displayed.
3.4 Static member functions
The static member functions are special functions used to access the static data members or other static member functions.
A member functions that is declared as static has the following properties
A static function can have access to only other static members functions or static variables declared in the same class.
A static member function can be called using the class name (instead of its objects) as follows
class-name:: function-name;
If the static member function accesses any non-static data member or non-static member function, it throws an error.
A count of number of objects created in maintained by the static variable count.
Program 3.4 (Static member function).
The static function showcode()
displays the number of objects created.
#include<iostream>
#include<conio.h>
using namespace std;
class test
{
int code;
static int count; // static member variable
public:
void setcode(void)
{
code=++count;
}
void showcode(void)
{
cout<<"Object number: "<<code<<"\n";
}
static void showcount(void) // static member function
{
cout<<"count: "<<count<<"\n";
}
};
int test::count;
int main()
{
test t1, t2;
t1.setcode();
t2.setcode();
test::showcount(); // accessing static function
test t3;
t3.setcode();
test::showcount();
t1.showcode();
t2.showcode();
t3.showcode();
return 0;
}
The output would be
count: 2
count: 3
Object number: 1
Object number: 2
Object number: 3
Note :
code=++count;
is executed whenever setcode()
function is invoked and the current value of count is assigned to code. Since object has its own copy of code, the value contained in code represents a unique number of its object.
Remember, the below code not work
static void showcount()
{
cout << code; // because code is not static
}
3.5 Array of objects
An array can be of any data type including struct. Similarly, we also have arrays of variables that are of the type of class. Those variables are called Arrays of Objects. Consider the following class definition
class employee
{
char name[30];
int age;
public:
void getdata(void);
void putdata(void);
};
The identifier employee is a user-defined data type and it is used to create objects that relate to different categories of the employee.
employee manager[3];
employee foreman[15];
employee worker[75];
The array manager contains two objects(manager) namely manager[0], manager[1]
and manager[2]
of type employee class. Similarly the foreman array contains 15 objects(foreman) and the worker array contains 75 objects(workers).
An array of objects is stored inside the memory in the same way as a multi-dimensional array- The array manager in represented in the below figure.
Note that only the space for data item of the objects is created. Member functions are stored separately and will be used by all the objects.
Program 3.5 (Arrays of objects).
#include<iostream>
using namespace std;
class employee
{
char name[30]; // string as class member
float age;
public:
void getdata(void);
void putdata(void);
};
void employee :: getdata(void)
{
cout <<"Enter name :" ;
cin >> name;
cout << "Enter age :" ;
cin >> age;
}
void employee :: putdata(void)
{
cout << "Name : " << name <<"\n";
cout << "Age : " << age <<"\n";
}
const int size=3;
int main()
{
employee manager[size];
for (int i=0; i <size ; i++)
{
cout << "\nDetails of manager " << i+1 << "\n";
manager[i].getdata();
}
cout << "\n";
for (int i=0; i<size ; i++)
{
cout << "\nManager "<< i+1 << "\n";
manager[i].putdata();
}
return 0;
}
The output would be
Details of manager 1
Enter name :XXX
Enter age :30
Details of manager 2
Enter name :YYY
Enter age :32
Details of manager 3
Enter name :ZZZ
Enter age :33
Manager 1
Name : XXX
Age : 30
Manager 2
Name : YYY
Age : 32
Manager 3
Name : ZZZ
Age : 33
3.6 Friendly functions
If a function is defined as a friend function in C++, then the protected and private data of a class can be accessed using the function.
By using the keyword friend compiler knows the given function is a friend function.
For accessing the data, the declaration of a friend function should be done inside the body of a class starting with the keyword friend.
We have simple declare this function as a friend of the class as shown below
class ABC
{
............
............
............
public:
............
............
friend void xyz(); // declaration
};
In the above declaration, the friend function is preceded by the keyword friend. The function can be defined anywhere in the program like a normal C++ function. The function definition does not use either the keyword friend or scope resolution operator.
A friend function although not a member function, has full access rights to the private member of the class.
A friend function possesses certain special characteristics
It is’nt in the scope of the class to which it has been declared as friend.
Since it is’nt in the scope of the class, it can’t be called using the object of that class.
It can be invoke like a normal function without the help of any object.
Unlike member functions, it can’t access the member names directly and has to use an object name and dot membership operator with each member name.
It can be declared either in the public or the private part of a class without affecting its meaning.
Usually, it has the objects as arguments.
Program 3.6 (Friend function).
#include<iostream>
using namespace std;
class sample
{
int a,b;
public:
void setvalue()
{
a=25;
b=40;
}
friend float mean(sample s);
};
float mean(sample s)
{
return float(s.a+s.b)/2.0;
}
int main()
{
sample x; // x object of type sample
x.setvalue();
std::cout<<"Mean Value="<<mean(x) << "\n";
}
The output would be
Mean Value=32.5
The friend function accesses the class variable a and b by using the dot operator and the object passed to it. The function call mean(x) passes the object X by value to the friend function.
Member functions of one class can be friend functions of another class. In such cases they are defined using the scope resolution operator which is show as follows
class X
{
........
........
int fun1(); // member function of x
........
};
class Y
{
........
........
friend int X:: fun1(); //fun1() of X is friend of y
........
};
The function fun1()
is a member of class X and a friend of class Y.
We can also declare all the member function of one class as the friend functions of another class. in such cases, the class is called a friend class.
This can be specified as follows
class Z
{
........
........
friend class X; // all member functions of X are friends to Z
};
Program 3.7 (Using friend function to add data objects of two different classes).
#include<iostream>
using namespace std;
class ABC; // forward declaration
class XYZ
{
int data;
public:
void setvalue(int value)
{
data=value;
}
friend void add(XYZ,ABC); // friend function declaration
};
class ABC
{
int data;
public:
void setvalue(int value)
{
data=value;
}
friend void add(XYZ,ABC); // friend function declaration
};
void add(XYZ obj1, ABC obj2) // definition of friend
{
cout << "Sum of data values of XYZ and ABC objects using friend function = "<< obj1.data+ obj2.data;
}
int main()
{
XYZ X;
ABC A;
X.setvalue(5);
A.setvalue(50);
add(X,A); // Calling friend function
return 0;
}
The output would be
Sum of data values of XYZ and ABC objects using friend function = 55
The function add()
has arguments from both XYZ and ABC. When the function add()
is declared as friend in XYZ for the first time, The compiler will not acknowledge the presence of ABC its name is declared in the beginning as class ABC;
This is known as forward declaration.
3.7 Returning objects
A function can’t only receive objects as arguments but also can return them.
In the below program take how an object can be created(with in function ) and return to another function.
Program 3.8 (Returning Objects).
#include<iostream>
#include<conio.h>
using namespace std;
class matrix
{
int m[3][3];
public:
void read(void)
{
cout << "Enter the elements of the 3 by 3 matrix : \n";
int i,j;
for (i=0; i<3; i++)
for(j=0;j<3; j++)
{
cout <<"m["<<i<<"]["<<j<<"] = ";
cin >>m[i][j];
}
}
void display (void)
{
int i,j;
for (i=0;i<3;i++)
{
cout <<"\n";
for(j=0;j<3;j++)
{
cout <<m[i][j]<<"\t";
}
}
}
friend matrix trans(matrix);
};
matrix trans(matrix m1)
{
matrix m2; // creating an object
int i,j;
for (i=0;i<3;i++)
for (j=0;j<3;j++)
m2.m[i][j]=m1.m[j][i];
return(m2); // returning object
}
int main()
{
matrix mat1, mat2;
mat1.read();
cout<<"\nYou enterd the following matrix :";
mat1.display();
mat2=trans(mat1);
cout<<"\nTranspose matrix :";
mat2.display();
getch();
return 0;
}
The output would be
Enter the elements of the 3 by 3 matrix :
m[0][0] = 1
m[0][1] = 2
m[0][2] = 3
m[1][0] = 4
m[1][1] = 5
m[1][2] = 6
m[2][0] = 7
m[2][1] = 8
m[2][2] = 9
You enterd the following matrix :
1 2 3
4 5 6
7 8 9
Transpose matrix :
1 4 7
2 5 8
3 6 9
3.8 Pointers to members
This is possible to take the address of a member of a class and assign it to a pointer. The address of a member can be obtained by applying the ampersand operator &
to a “fully qualified” class member name. A class member pointer can be declared using the operator ::* with the class name. The syntax is
class X
{
private:
int m;
public:
void show();
};
we can define a pointer to member m as follows:
int X::* ip=&X::m;
The ip pointer create thus acts like a class member in that it must be invoked with a class object. in the statement above the phrase X::*
means “pointer to pointer of X class” The phase &X::m
means the “address of the m member of X class”.
Note that the following statement is not valid
int *ip=&m; //won't work
It is because m is not simply an int data type. it has meaning only whenever it is associated with the class to which it belongs. The scope resolution operator must be applied to both the pointer and the member.
The pointer ip can now be used to access the member m inside member functions(or the friend functions) let us assume that x is an object of X declared in a member function.
We can access m using the pointer ip as follows
cout << x.*ip; // display
cout << x.m; // same as above
now look at the following code
ap=&&x; // ap is pointer to object X
cout << ap->*ip; // display m
cout << ap->m; // same as above
The dereferencing operator ->*
is used to access a member when we use pointers to both the object and the member. The dereferencing operator. * is used when the object itself is used with the member pointer.
Note that *ip is used like a member name.
Program 3.9 (Dereferencing operators ).
#include<iostream>
using namespace std;
class M
{
int x;
int y;
public:
void set_xy(int a,int b)
{
x=a;
y=b;
}
friend int sum(M m);
};
int sum(M m)
{
int M::*px=&M::x;
int M::*py=&M::y;
M *pm=&m;
int s=m.*px+pm->*py;
return s;
}
int main()
{
M n;
void (M::*pf)(int,int)=&M::set_xy;
(n.*pf)(10,20);
std::cout<<"sum=" <<sum(n)<<"\n";
M *op=&n;
(op->*pf)(30,40);
std::cout<<"sum="<<sum(n) <<"\n";
}
The output would be
sum=30
sum=70
3.9 Local classes
A class declared inside a function is known as a local class in C++ as it is local to that function.
A syntax of a local class is given as follows.
void test(int a) // function
{
........
........
class student // local class
{
........
........ // class definition
};
........
........
student s1(a); // create student object
........ // use student object
}
local classes can use global variable(declared above in function) and static variables declared inside the function but cannot use automatic variables. The global variables name(variables) should be used with the (::)scope Resolution operator.
There are some of the restrictions in constructing local classes. They have static data members and member functions must be defined inside the local classes. They can’t have static data members and member functions must be defined inside the local classes. Enclosing function cannot access the private members of the local class.
However we can achieve this by declaring the enclosing function as a friend.
Program 3.10 (Local classes).
#include <iostream>
using namespace std;
//A user defined function
void testFunction(void)
{
//declaring a local class
//which is accessible within this function only
class Test1
{
private:
int num;
public:
void setValue(int n)
{
num = n;
}
int getValue(void)
{
return num;
}
};
//any message of the function
cout<<"Inside testFunction..."<<endl;
//creating class's object
Test1 T1;
T1.setValue(100);
cout<<"Value of Test1's num: "<<T1.getValue()<<endl;
}
//Main function
int main()
{
//declaring a local class
//which is accessible within this function only
class Test2
{
private:
int num;
public:
void setValue(int n)
{
num = n;
}
int getValue(void)
{
return num;
}
};
//calling testFunction
cout<<"Calling testFunction..."<<endl;
testFunction();
//any message of the function
cout<<"Inside main()..."<<endl;
//creating class's object
Test2 T2;
T2.setValue(200);
cout<<"Value of Test2's num: "<<T2.getValue()<<endl;
return 0;
}
The output would be
Calling testFunction...
Inside testFunction...
Value of Test1's num: 100
Inside main()...
Value of Test2's num: 200
Here, we are declaring and defining two classes Test1 and Test2, Test1 is declared inside a user-defined function named testFunction()
and Test2 is declares inside the main()
function.
Since classes Test1 and Test2 are declared within the functions, thus, their scope will be local to those functions. Hence, Test1 and Test2 are local classes in C++.
4 Constructors and Destructor
Constructors
A constructor is a special member function whose task is to initialize the objects of its class it is very special because its name is same as the class name. The constructor is automatically invoked whenever an object of its associated class is created. It is called constructor because it constructors the value of data member of the class.
The syntax of constructor is declared and defined in the below
/ class with a constructor
class interger
{
int m,n;
public:
integer(); // declared constructor
..........
..........
};
integer :: integer() // define constructor
{
m=0; n=0;
}
The constructor functions have some special characteristic these are:
They should be declared in the public (scope)section.
They are involved automatically when the object are created .
They do not have return type, not even void and therefore and they cannot return values.
They cannot be inherit, through a derived class can call the base class constructor.
Like other functions in C++ language, they can have default arguments.
We can not refer to their address.
Constructor can not be virtual.
They make implicit calls two operators new and delete when memory allocation is required.
An object with a constructor (or destructor) cannot be used as a member of a union.
Program 4.1 (Constructors).
// defining the constructor within the class
#include <iostream>
using namespace std;
class student {
int rno;
char name[10];
double fee;
public:
student()
{
cout << "Enter the RollNo:";
cin >> rno;
cout << "Enter the Name:";
cin >> name;
cout << "Enter the Fee:";
cin >> fee;
}
void display()
{
cout << endl << rno << "\t" << name << "\t" << fee;
}
};
int main()
{
student s; // constructor gets called automatically when
// we create the object of the class
s.display();
return 0;
}
The output would be
Enter the RollNo:112
Enter the Name:Seba
Enter the Fee:1400
112 Seba 1400
4.1 Parameterized Constructor
If a Constructor has parameters, it is called a Parameterized Constructor. Parameterized Constructors assist in initializing values when an object is created.
General Syntax of Parameterized Constructor
class integer
{
int m,n;
public:
integer(int x,int y); // parameterized constructor
.........
.........
};
integer::integer(int x,int y)
{
m=x;
n=y;
}
when a constructor has been parameterized, the object declaration of integer class statement such as
integer int1;
may not be work. we have to pass the initial values as arguments to the constructor when an object is declared.
This can be done in two types
by calling the constructor explicitly
by calling the constructor implicitly
The following declaration illustrates the first method
integer int1=integer(0,100); // explicitly call
This statement creates an integer object int1 and passes the values zero (0) and 100(Hundred) to it. The second is implemented as follows
integer int1(0,100); //this is implicit calling
This method, sometimes called the shorthand method is used very often as it is shorter looks better and is easy to implement.
Remember, when the constructor is parameterized, we must provide appropriate arguments for the constructor.
Program 4.2 (Parametrized constructor).
#include<iostream>
using namespace std;
class integer
{
int m,n;
public:
integer(int,int); // constructor declared
void display()
{
cout <<"m="<<m<<"\n";
cout <<"n="<<n<<"\n";
}
};
integer:: integer(int x,int y) // define constructor
{
m=x;
n=y;
}
int main()
{
integer int1(0,100); // constructor called implicitly
integer int2=integer(25,75); // constructor called explicitly
std::cout<<"\nobject1" << "\n";
int1.display();
std::cout<< "\nobject2" << "\n";
int2.display();
return 0;
}
The output would be
object1
m=0
n=100
object2
m=25
n=75
The constructor function can also be defined as inline functions. Examples
class integer
{
int m,n;
public:
integer(int x,int y) // inline constructor
{
m=x;
y=n;
}
.................
.................
};
The paramters of a constructor can be any type except that of the class to which it belongs to for example
class A
{
................
................
public:
A(A);
};
Thus the statement is illegal because however, a constructor can accept a reference to its own class as a parameter.
Class All
{
................
................
public:
A(A&);
};
is valid in such cases the constructor is called the copy constructor.
4.2 Multiple constructor in a class
So far we have used two kinds of constructor. They are
integer(); // no arguments
integer(int,int) // two arguments
In the first case, the constructor integer() itself supplies the data values and no values are passed by the calling program. In the second case the function call passes the appropriate values from main(). C++ permits use to both these constructors in the same class.
For example in the below we could define a class as follows
class integer
{
int m,n;
public:
integer() // constructor first
{
m=0;
n=0;
}
integer(int a,int b) // constructor second
{
m=a;
n=b;
}
integer(integer &i) // constructor Third
{
m=i.m;
n=i.n;
}
};
This declares three constructor for an integer object. So The first constructor receives no arguments, and The second case receive two integer arguments and the third receives one integer object as an argument. For example, the declaration
integer I1;
would automatically invoke first constructor and set both m and n of I1 to zero. The statement
integer I2(20,40);
would call the second constructor which will initialize the data members m , n of I2 to 20 and 0 respectively. Finally the statement
integer I3(I2);
would invoke the third constructor which copies the values of I2 into I3.
Program 4.3 (Overloaded constructors).
#include<iostream>
using namespace std;
class complex
{
float x, y;
public :
complex(){} //constructor no argument
complex(float a){x=y=a;} // constructor one argument
complex(float real, float imag){x=real;y=imag;} //constructor two argument
friend complex sum(complex, complex);
friend void show(complex);
};
complex sum(complex c1,complex c2) //friend
{
complex c3;
c3.x=c1.x + c2.x;
c3.y=c1.y + c2.y;
return(c3);
}
void show(complex c) // friend
{
cout << c.x << " + j"<< c.y<<"\n";
}
int main()
{
complex A(2.7, 3.5); // define & initialize
complex B(1.6); // define & initialize
complex C; // define
C=sum(A,B); // sum() is friend
cout << "A ="; show (A); //show() i also friend
cout << "B ="; show (B);
cout << "C ="; show (C);
return 0;
}
The output would be
A =2.7 + j3.5
B =1.6 + j1.6
C =4.3 + j5.1
4.3 Copy constructor
The copy constructor is a constructor which creates an object by initializing it with an object of the same class, which has been created previously. The copy constructor is used to
Initialize one object from another of the same type.
Copy an object to pass it as an argument to a function.
Copy an object to return it from a function.
If a copy constructor is not defined in a class, the compiler itself defines one. If the class has pointer variables and has some dynamic memory allocations, then it is a must to have a copy constructor. The most common form of copy constructor is shown here
classname (const classname &obj) {
// body of constructor
}
Here, obj is a reference to an object that is being used to initialize another object.
As mentioned earlier, a copy constructor is used for declare and initialize an object from another object below example
integer I2(I1);
would define the object I2 and at the same time initialize it to the value of I1. Another form of This statement is
Integer I2=I1;
The process of initializing through a copy constructor is known as copy initialization.
A copy constructor takes a reference of an object of the same class as itself as an argument.
Program 4.4 (Copy constructor).
#include<iostream>
using namespace std;
class code
{
int id;
public :
code(){} // constructor
code(int a){id =a;} // constructor again
code(code &x) // copy constructor
{
id = x.id; //copy the value
}
void display(void)
{
cout << id ;
}
};
int main()
{
code A(100); // Object A is created and initilized
code B(A); // copy constructor called
code C=A; // copy constructor called again
code D; // D is created not initilized
D=A; // copy constructor not called
cout << "\n id of A :" ; A.display();
cout << "\n id of B :" ; B.display();
cout << "\n id of C :" ; C.display();
cout << "\n id of D :" ; D.display();
return 0;
}
The output would be
id of A :100
id of B :100
id of C :100
id of D :100
When no copy constructor is defined the compiler supplies its own copy constructor.
4.4 Dynamic constructor
The constructor can also be used to allocate(creating) memory while creating object. This will enable the system to allocate the correct amount of memory for each object when the objects are not of the same size, so resulting in the saving of memory. allocation of the memory to objects at the time of their construction is know as dynamic construction of objects.
The memory is allocated with new operator. in the program show the use of new.
When allocation of memory is done dynamically using dynamic memory allocator new in a constructor, it is known as dynamic constructor. By using this, we can dynamically initialize the objects.
Program 4.5 (Constructors with new).
#include<iostream>
#include<cstring>
using namespace std;
class String
{
char *name;
int length;
public :
String ()
{
length=0;
name=new char[length+1];
}
String (char *s) // constructor 2
{
length=strlen(s);
name=new char[length+1]; //one additional
strcpy(name,s); // character for \0
}
void display()
{
std::cout<<name <<"\n";
}
void join(String &a,String &b);
}; void String:: join(String &a,String &b)
{
length=a.length+b.length;
delete name;
name=new char[length+1]; // dynamic allocation
strcpy(name,a.name);
strcat(name,b.name);
};
int main()
{
char *first="joseph";
String name1(first),name2("louis"),name3("lagrange"),s1,s2;
s1.join(name1,name2);
s2.join(s1,name3);
name1.display();
name2.display();
name3.display();
s1.display();
s2.display();
}
The output would be
Joseph
Louis
Lagrange
Joseph Louis
Joseph Louis Lagrange
In the above program uses two constructs the first is an empty construct that allows us to declare an array of string. The second construct initializes the length of the string, allocates necessary space of the string to be stored and creates the string itself, allocate necessary space for the string to be stored and created the string itself.
Note that one additional character space is allocated to hold the end of string character \0
.
The member function join()
concatenates two string. It estimates the combined length of the string to be joined, allocates memory for the combined string and then create the same using the string function strcpy()
and strcat()
.
Note that in the function join()
length members of the argument object a. The main()
function program concatenates three strings into one string.
4.5 Constructing two dimensional arrays
In C++ Two Dimensional array in C++ is an array that consists of more than one rows and more than one column. In 2-D array each element is refer by two indexes. Elements stored in these Arrays in the form of matrices. The first index shows a row of the matrix and the second index shows the column of the matrix.
Syntax of Two-Dimensional Array
(Data type) (Name of array) [Number of rows] [Number of columns];
For example
Int matrix [7] [7];
When we type the above statement the compiler will generate a 2-D array of a matrix which consists of 7 rows and 7 columns.
Program 4.6 (Creating matrix).
#include <iostream>
using namespace std;
int main()
{
int test[3][3] =
{
{2, 5, 5},
{4, 0, 3},
{9, 1, 8} }; //declaration and initialization
//traversal
for(int i = 0; i < 3; ++i)
{
for(int j = 0; j < 3; ++j)
{
cout<< test[i][j]<<" ";
}
cout<<"\n"; //new line at each row
}
return 0;
}
The output would be
2 5 5
4 0 3
9 1 8
Program 4.7 (Constructing matrix objects).
#include <iostream>
using namespace std;
class matrix
{
int **p; // pointer to matrix
int d1,d2; // dimensions
public:
matrix(int x,int y);
void get_element(int i,int j,int value)
{
p[i][j]=value;
}
int & put_element(int i,int j)
{
return p[i][j];
}
};
matrix::matrix(int x,int y)
{
d1=x;
d2=y;
p=new int *[d1]; // creates an array pointer
for ( int i=0; i < d1;i++)
{
p[i]=new int[d2]; // creates space for each row
}
}
int main()
{
int m,n;
std::cout<< "Enter size of matrix ";
std::cin>> m >> n;
matrix A(m,n);
cout << "Enter matrix elements row by row \n";
int i,j,value;
for (i=0;i < m;i++)
{
for (j=0;j < n;j++)
{ cin>> value;
A.get_element(i,j,value);
}
}
cout<< "\nThe element of A(1,2) is ";
cout<< A.put_element(1,2);
return 0;
};
The output would be
Enter size of matrix 3 4
Enter matrix elements row by row
11 12 13 14
15 16 17 18
19 20 21 22
The element of A(1,2) is 17
The constructor first creates a vector pointer to an int of size d1. Then it allocates iteratively an int type vector of size d2 pointed at by each element p[i]. Thus space for the elements of a d1 × d2 matrix is allocated from free store as shown.
4.6 Destructor
A destructor works opposite to constructor; it destructs the objects of classes. It can be defined only once in a class. Like constructors, it is invoked automatically.
Destructor is also a special member function like constructor. Destructor destroys the class objects created by constructor.
Destructor has the same name as their class name preceded by a tilde (
~
) symbol.It is not possible to define more than one destructor.
The destructor is only one way to destroy the object create by constructor. Hence destructor can-not be overloaded.
Destructor neither requires any argument nor returns any value.
It is automatically called when object goes out of scope.
Destructor release memory space occupied by the objects created by constructor.
In destructor, objects are destroyed in the reverse of an object creation.
The syntax of destructor is
class X {
public:
// Constructor for class X
X();
// Destructor for class X
~X();
};
The thing is to be noted here, if the object is created by using new or the constructor uses new to allocate memory which resides in the heap memory or the free store, the destructor should use delete to free the memory.
#include<iostream>
using namespace std;
int count=0;
class Test
{
public:
Test()
{
count++;
cout<<"\n No. of Object created:\t"<<count;
}
~Test()
{
cout<<"\n No. of Object destroyed:\t"<<count;
--count;
}
};
int main()
{
Test t1,t2,t3,t4;
return 0;
}
The output would be
No. of Object created: 1
No. of Object created: 2
No. of Object created: 3
No. of Object created: 4
No. of Object destroyed: 4
No. of Object destroyed: 3
No. of Object destroyed: 2
No. of Object destroyed: 1
5 Operator Overloading
Introduction
You can redefine or overload the function of most built-in operators in C++. These operators can be overloaded globally or on a class-by-class basis. Overloaded operators are implemented as functions and can be member functions or global functions.
An overloaded operator is called an operator function. You declare an operator function with the keyword operator preceding the operator. Overloaded operators are distinct from overloaded functions, but like overloaded functions, they are distinguished by the number and types of operands used with the operator.
Almost all operators can be overloaded except a few. Following is the list of operators that cannot be overloaded.
sizeof
typeid
Scope resolution (::)
Class member access operators (.(dot), .* (pointer to member operator))
Ternary or conditional (?:)
Operators that can be overloaded
Binary Arithmetic
+, -, *, /, %
Unary Arithmetic
+, -, ++, —
Assignment
=, +=,*=, /=,-=, %=
Bit- wise
&
, ∣,<< , >> , ~ , ^
De-referencing
(->)
Dynamic memory allocation and De-allocation
New, delete
Subscript
[ ]
Function call
()
Logical
&
,!
Relational
>, < , = =, <=, >=
Defining operator overloading
To define an additional task to an operator, we must specify what it means in relation to the class to which the operator is applied. This is done with the help of a special function, called operator function, which describes the task. The general form of an operator function is
return type classname: : operator (op arglist)
{
Function body // task defined
}
Where return type is the type of value returned by the specified operation and op is the operator being overloaded. The op is preceded by the keyword operator. Operator op is the function name.
Operator function must be either member functions (non – static) or friend functions. It is declared in the class using prototypes as follows:
vector operator+(vector); |
// vector addition |
vector operator-(); |
// unary minus |
friend vector operator+(vector,vector); |
// vector addition |
friend vector operator – (vector); |
// unary minus |
vector operator- (vector &a); |
// subtraction |
int operator ==(vector); |
// comparison |
friend int operator==(vector,vector) |
// comparison |
vector is a data type of class and may represent both magnitude and direction or a series of points called elements.
The process of overloading involves the following steps:
Create a class that defines the data type that is to be used in the overloading operation.
Declare the operator function operator op() in the public Area of the class. It may be either a member function or a friend function.
Define the operator function to implement the required operations.
Overloaded operator functions can be invoked by expressions such as
op x or x op
for unary operators and
x op y
for binary operators. op x(or x op) would be interpreted as
operator op (x)
for friend functions. Similarly the expression x op y would be interpreted as either
x.operator op (y)
in case of member functions, or
operator op (x,y)
in case of friend functions.
5.1 Overloading unary operators
To conduct mathematical and logical operations on numerical quantities, C++ includes a wide variety of operators. The unary operators are one such extensively used operator. Unary Operators work on the operations carried out on just one operand. Unary operators do not utilize two operands to calculate the result as binary operators do.
A single operand/variable is used with the unary operator to determine the new value of that variable. Unary operators are used with the operand in either the prefix or postfix position. Unary operators come in various forms and have right-to-left associativity and equal precedence.
These are some examples of unary operators:
Increment operator
(++)
,Decrement operator
(--)
,Unary minus operator
(-)
,Logical not operator
(!)
,Address of
(&)
, etc.
Let’s understand unary operator overloading in C++ by using the following program.
Program 5.1 (Overloading unary minus operator).
#include<iostream>
using namespace std;
class space
{
int x, y, z;
public:
void getdata(int a, int b, int c);
void display(void);
void operator-(); //overload unary minus
};
void space :: getdata(int a, int b, int c)
{
x=a;
y=b;
z=c;
}
void space::display(void)
{
cout << "x = " <<x << " ";
cout << "y = " <<y << " ";
cout << "z = " <<z << "\n";
}
void space :: operator-()
{
x=-x;
y=-y;
z=-z;
}
int main ()
{
space S;
S.getdata(10,-20,30);
cout << "S : ";
S.display();
//Activate operator-() function
-S;
cout<<"-S : ";
S.display();
return 0;
}
The output would be
S : x = 10 y = -20 z = 30
-S : x = -10 y = 20 z = -30
Remember, a statement like
S2=-S1
will not work because, the function operator-()
does not return any value.
5.2 Overloading binary operators
We have just seen in previous page how to overload a unary operator. In the same mechanism can be used to overload the binary operator. Already we have seen, how to add two complex numbers using a friend function. A statement like
C = sum(A, B); // it is functional notation.
was used. The functional notation can be replaced by a natural looking expression
C = A + B; // arithmetic notation
by overloading the + operator using an operator+()
function.
The following program illustrates how this is accomplished.
Program 5.2 (Overloading + operator).
# include <iostream>
using namespace std;
class complex
{
float x; // real part
float y; // imaginary part
public : complex() { } // constructor 1
complex(float real, float imag) // constructor 2
{
x = real;
y = imag;
}
complex operator + (complex);
void display(void);
};
complex complex :: operator+(complex c)
{
complex temp; //temporary
temp.x = x + c.x; // these are
temp.y = y + c.y; // statement for float additions
return(temp);
}
void complex :: display(void)
{
std::cout << x << " + j" << y << "\n";
}
int main()
{ complex C1, C2, C3; // invokes constructor 1
C1 = complex (2.5, 3.5); // invokes constructor 2
C2 = complex (1.6, 2.7);
C3 = C1 + C2;
std::cout << "C1 = "; C1.display();
std::cout << "C2 = "; C2.display();
std::cout << "C3 = "; C3.display();
return 0;
}
The output would be
C1 = 2.5 + j3.5
C2 = 1.6 + j2.7
C3 = 4.1 + j6.2
Let us have a close look at the function operator+ ()
and see how the operator overloading is implemented.
complex complex : : operator+ (complex c)
{
complex temp;
temp.x = x + c.x;
temp.y = y + c.y;
return(temp) ;
}
We should note the following features of this function:
It receives only one complex type argument explicitly.
It returns a complex type value.
It is a member function of complex.
The function is expected to add two complex values and return a complex value as the result but receives only one value as argument. Where does the other value come from? Now let us look at the statement that invokes this function:
C3 = C1 + C2; // invokes operator+() function
We know that a member function can be invoked only by an object of the same class. Here, the object C1 takes the responsibility of invoking the function and C2 plays the role of an argument that is passed to the function. The above invocation statement is equivalent to
C3 = C1. operator+(C2); // usual function call syntax
Therefore, in the operator+()
function, the data members of C1 are accessed directly and the data members of C2 (that is passed as an argument ) are accessed using the dot operator. Thus, both the objects are available for the function. For example, in the statement
temp.x = x + c.x;
c.x refers to the object C2 and x refers to the object C1.temp.x is the real part of temp that has been created specially to hold the results of addition of C1 and C2. The function returns the complex temp that has been created specially to hold the results of addition of C1 and C2. The function returns the complex temp to be assigned to C3.in Figure show how this is implemented.
As a rule, in overloading of binary operators, the left-hand operand is used to invoke the operator function and the right-hand operand is passed as an argument.
We can avoid the creation of the temp object by replacing the entire function body by the following statement:
return complex((x+c.x), y+c.y)); //invokes constructor 2
What does it mean when we use a class name with an argument list? When the complier comes across a statement like this, it invokes an appropriate constructor, initializes an object with no name and returns the contents for copying into an object. Such an object is called a temporary object and goes out of space as soon as soon as the contents are assigned to another object. Using temporary objects can make the code shorter, more efficient and better to read.
5.3 Rules for overloading operators
Although it looks simple to redefine the operators, There are certain restrictions and limitations in overloading them, some of them are listed below
Only existing operators can be overloaded. now operators cannot be created
The overloaded operator must have at least one operand that is type of user defined.
We can’t change the basic meaning of an operator. That is to say we cannot redefine the plus(+) operator to subtract one value from the other.
The Overloaded operators follows the rules of the original operators. They cannot be overridden.
There are some operators that can’t be overloaded.
we can’t use friend functions to overload certain operators. however the member function can be used to overload them .
The unary operators, overloaded by the member function, take no explicit arguments and also no explicit values return, but those overloaded by means of a friend function, take one reference argument.
Binary operator overloaded through a member function take two explicit arguments
When using the binary operators overloaded using a member function, the left hand side operand must be an object of the relevant class.
Binary arithmetic operators such as
*,+,-
and/
must be explicitly return the value, they must not attempt to change their own arguments.
Operators that can not be overloaded
Sizeof | size of operator |
. * |
Membership operator |
:: |
scope resolution operator |
?: |
Conditional operator |
Where a friend cannot be used
= |
assignment operator |
() |
Function call operator |
[] |
subscripting operator |
-> |
class member access operator |
5.4 Defining derived classes
A derived class is defined by specifying it relationship with the base class in addition to its own details.
The general form of defining a derived class is
class derived-class-name : visibility-mode base-class-name
{
...
... //members of derived class
...
};
where,
class is the required keyword,
derived-class-name is the name given to the derived class,
base-class-name is the name given to the base class,
: (colon) indicates that the derived-class-name is derived from the base-class-name,
visibility-mode is optional and, if present, may be either private or public. The default visibility-mode is private. Visibility mode specifies whether the features of the base class are privately derived or publicly derived. Example
class ABC : private XYZ //private derivation
{
members of ABC
};
class ABC : public XYZ //public derivation
{
members of ABC
};
class ABC : XYZ //private derivation by default
{
members of ABC
};
When a base class is privately inherited by a derived class, ‘public member’ of the base class becomes private members of the derived class and therefore the public members of the base class can only be accessed by the member functions of the of the derived class. They are inaccessible to the objects of the derived class.
Remember, a public member of the class can be accessed by its own objects by using the dot operator. The result is that no member of the base class is accessible to the objects of the derived class in case of private derivation.
On the other hand, when the base class is publicly inherited, ‘public members’ of the base class becomes ‘public members’ of the derived class and therefore they are accessible to the objects of the derived class.
In both the cases, the private members are not inherited and therefore, the private members of a base class will never become the members of its derived class.
In inheritance, some of the base class data elements and member functions are inherited into the derived clas. We can also add our own data and member functions and thus extend the functionality of the base class. Inheritance, when used to modify and extend the capabilities of the existing classes, becomes a very powerful tool for incremental program development.
5.5 Single inheritance
Let us consider a simple example to understand single inheritance in the below program show a base class B and a derived class D. The class B consist one private data member, one public data member, and three public member functions. The class D contains one private data member and two public member functions.
#include<iostream>
using namespace std;
class B
{
int a; // private not inheritable
public:
int b; // public, ready for inheritable
void set_ab();
int get_a(void);
void show_a(void);
};
class D : public B // public derivation
{
int c;
public:
void mul(void);
void display(void);
};
void B :: set_ab(void)
{
a=5; b=10;
}
int B :: get_a()
{
return a;
}
void B ::show_a()
{
cout << "a = "<< a<< "\n";
}
void D :: mul()
{
c=b*get_a();
}
void D:: display()
{
cout <<"a = " << get_a() << "\n";
cout <<"b = "<< b << "\n";
cout <<"c = "<< c << "\n\n";
}
int main()
{
D d;
d.set_ab();
d.mul();
d.show_a();
d.display();
d.b=20;
d.mul();
d.display();
return 0;
}
The output would be
a = 5
a = 5
b = 10
c = 50
a = 5
b = 20
c = 100
In the above program, following things require to be noted:
The class D is a public derivation of the base class B. Therefore, class D inherits all the public members of class B an retains their visibility. Thus, a public member of the base class B is also a public member of the derived class D
The private members of the base class B cannot be inherited by the derived class D
The class D, in effect, will have more members than what it contains at the time of declaration
The program illustrates that the objects of class D have access to all the public members of class B
Let us have a look at the function show_a()
and mul()
void show_a()
{
cout<<"a="<< a << "\n";
}
void mul()
{
c=b*get_a(); // means c=b*a
}
so here the data member a is private in B and cannot be inherited, objects of D are able to access it through an inherited member function of B.
Let us now consider the case of private derivation
class B
{
int a;
public :
int b:
void get_data();
void get_a();
void show_a();
};
class D : private B // private derivation
{
int C;
public :
void mul();
void display();
};
The membership of the derived class D is in private derivation, the public members of the base class become private members of the derived class. Therefore the objects of D can not have direct access to the public member function of B. The statement such as
d.get_ab(); // get_ab() is private
d.get_a(); // so also get_a()
d.show_a(); // and show_a()
will not work. however, These functions can be used inside mul()
and display like the normal functions as shown below
void mul()
{
get_data();
c=b*get_a();
}
void display()
{
show_a(); // outputs value of a
cout << "b=" << b << "\n" << "c=" << c << "\n\n";
}
Incorporates these modifications in private derivation.
Program 5.3 (Single inheritance : Private).
#include<iostream>
using namespace std;
class B
{
int a; // private not inheritable
public:
int b; // public, ready for inheritable
void get_ab();
int get_a(void);
void show_a(void);
};
class D : public B // public derivation
{
int c;
public:
void mul(void);
void display(void);
};
void B :: get_ab(void)
{
cout<<"Enter the values for a and b :" ;
cin >>a >> b;
}
int B :: get_a()
{
return a;
}
void B ::show_a()
{
cout << "a = "<< a<< "\n";
}
void D :: mul()
{
get_ab();
c=b*get_a(); // a can not be used directly
}
void D:: display()
{
show_a();
cout <<"b = "<< b << "\n";
cout <<"c = "<< c << "\n\n";
}
int main()
{
D d;
// d.set_ab(); // won't work
d.mul();
//d.show_a(); // won't work
d.display();
//d.b=20; // won't work; b have become private
d.mul();
d.display();
return 0;
}
The output would be
Enter the values for a and b :5 6
a = 5
b = 6
c = 30
Enter the values for a and b :7 9
a = 7
b = 9
c = 63
5.6 Multi-Level inheritance
The mechanism of deriving a class from another derived class is known as multi-level inheritance in C++.
It is not uncommon that a class is derived from another derived class as shown below:
The class A serves as a base class for the derived class B which in turn serves as a base class for the derived class C. The class B is known as intermediate base class since it provides a link for the inheritance between A and C. The chain A -> B -> C
is known as inheritance path.
A derived class with multi-level inheritance is declared as follows:
class A //Base Class
{
...
};
class B : public A //B derived from A
{
...
};
class C : public B //C derived from B
{
...
};
This process can be extended to any number of levels.
Let us consider the below example:
Assume that the test results of a batch of students are stored in three different classes. class student stores the roll-number, class test stores the marks obtained in two subjects and class result contains the total marks obtained in the test. The class result can inherit the details of the marks obtained in the test and the roll-number of the students through multilevel inheritance.
class student
{
protected:
int roll_number;
public:
void get_number(int);
void put_number(void);
};
void student :: get_number(int a)
{
roll_number = a;
}
void student :: put_number()
{
cout << "Roll Number: " << roll_number << endl;
}
class test : public student //First level derivation
{
protected:
float sub1;
float sub2;
public:
void get_marks(float, float);
void put_marks(void);
};
void test :: get_marks(float x, float y)
{
sub1 = x;
sub2 = y;
}
void test :: put_marks()
{
cout << "Marks in Sub1 = " << sub1 << endl;
cout << "Marks in Sub2 = " << sub2 << endl;
}
class result : public test //second Level Derivation
{
float total; //private by default
public:
void display();
};
The class result in the above example, after inheritance from B to C, would contain the following members:
private:
float total; //own member
protected:
int roll_number; //inherited from student via test
float sub1; //inherited from test
float sub; //inherited from test
public:
void get_number(int); //from student via test
void put_number(void); //from student via test
void get_marks(float, float); //from test
void put_marks(void); //from test
void display(void); //own member
The inherited functions put_numbers()
and put_marks()
can be used in the definition of display()
function as follows:
void result :: display(void)
{
total = sub1 + sub2;
put_number();
put_marks();
cout << "Total = " << total << endl;
}
Here is a simple main()
program based on the above defined class result:
int main()
{
result student1; //student1 object created
student1.get_number(786);
student1.get_marks(71.5, 99.5);
student1.display(); //display the result of student1
}
The complete program is given below.
Program 5.4 (Multilevel inheritance).
#include<iostream>
using namespace std;
class student
{
protected:
int roll_number;
public:
void get_number(int);
void put_number(void);
};
void student :: get_number(int a)
{
roll_number = a;
}
void student :: put_number()
{
cout << "Roll Number: " << roll_number << endl;
}
class test : public student //First level derivation
{
protected:
float sub1;
float sub2;
public:
void get_marks(float, float);
void put_marks(void);
};
void test :: get_marks(float x, float y)
{
sub1 = x;
sub2 = y;
}
void test :: put_marks()
{
cout << "Marks in Sub1 = " << sub1 << endl;
cout << "Marks in Sub2 = " << sub2 << endl;
}
class result : public test //second Level Derivation
{
float total; //private by default
public:
void display();
};
void result :: display(void)
{
total = sub1 + sub2;
put_number();
put_marks();
cout << "Total = " << total << endl;
}
int main()
{
result student1; //student1 object created
student1.get_number(111);
student1.get_marks(71.5, 99.5);
student1.display(); //display the result of student1
return 0;
}
The output would be
Roll Number: 111
Marks in Sub1 = 71.5
Marks in Sub2 = 99.5
Total = 171
5.7 Multiple Inheritance
Inheritance in which a derived class is derived from several base class is known as multiple inheritance.
A class can inherit the attributes of two or more classes as shown in fig. below. This is known as multiple inheritance.
Multiple inheritance allows us to combine the features of several existing classes as a starting point for defining new classes. It is like a child inheriting the physical features of one parent and the intelligence of another.
The syntax of a derived class with multiple base class is as follows:
class D : visibility B-1, visibility B-2...
{
...
... (Body of D)
...
};
where visibility may be either public or private. The base classes are separated by commas. Example:
class P : public M, public N
{
public:
void display(void);
};
Classes M and N have been specified as follows:
class M
{
protected:
int m;
public:
void get_m(int);
};
void M :: get_m(int x)
{
m = x;
}
class N
{
protected:
int n;
public:
void get_n(int);
};
void N :: get_n(int y)
{
n = y;
}
The derived class P, as declared above would, in effect, contain all the members of M and N in addition to its own members as shown below
class P
{
protected:
int m; //from the class M
int n; //from the class N
public:
void get_m(int); //from the class M
void get_n(int); //from the class N
void display(void); //own member
};
The member function display() can be defined as follows
void P:: display(void)
{
std::cout << "m=" << m << "\n";
std::cout << "n" << n << "\n";
std::cout << "m*n=" << m*n << "\n";
};
The main()
function of the program based on the above defined class P may be written as follows
main()
{
P x;
x.get_m(10);
x.get_n(15);
x.display();
}
The following program shows the entire code illustrating how all the three classes are implemented in the multiple inheritance mode.
Program 5.5 (Multiple inheritance).
#include<iostream>
using namespace std;
class M
{
protected:
int m;
public:
void get_m(int);
};
class N
{
protected:
int n;
public:
void get_n(int);
};
class P : public M, public N
{
public:
void display(void);
};
void M :: get_m(int x)
{
m = x;
}
void N :: get_n(int y)
{
n = y;
}
void P:: display(void)
{
cout << "m = " << m << "\n";
cout << "n = " << n << "\n";
cout << "m * n =" << m*n << "\n";
};
int main()
{
P p;
p.get_m(10);
p.get_n(15);
p.display();
return 0;
}
The output would be
m = 10
n = 15
m * n =150
5.7.1 Ambiguity resolution in inheritance
Occasionally, we may face a problem in using the multiple inheritance, when a function with the same inheritance appears in more than one base class. Consider the following two classes
class M
{
public:
void dipslay()
{
std::cout << "class M\n";
}
};
class N
{
public:
void display()
{
std::cout << "class N\n";
}
};
which display() function is used by the derived class when we inherit these two classes? we can solve this problem by defining a named instance within the derived class, using the class resolution operator with the function as shown
class P: public M, public N
{
public:
void display()
// overrides display() of N and M
{
M::display();
}
};
we can now use the derived class as follows
int main()
{
P p;
p.display();
}
Ambiguity may also arise in single inheritance application, for instance, consider the follow situation:
class A
{
public:
void display()
{
std::cout<<"A\n";
};
class B: public A
{
public:
void display()
{
std::cout<<"B\n";
}
};
in this case the function in the derived class overrides the inheritance the inherited function and therefore, a simple call to display() by B type will invoke function defined in B only. however we may invoke the function defined in A by using the scope resolution operator to specify the class Example
void main()
{
B b; // derived class object
b.display(); //invokes display() in B
b.A::display(); // invokes display() in A
b.B::display(); // invokes display() in B
}
This will produce the following output:
B
A
B
5.8 Hierarchical inheritance
In C++ such problems can be easily convert into class heirarchies. The base class will include all features that are common to subclasses . A subclasses. A subclass can be constructed by inheriting the properties if the base class.
A subclass can be constructed by using inheriting the properties of the base class.
A subclass can serve as a base class for the lower level class and so on.
You can use the following syntax to achieve Hierarchical Inheritance in C++:
class base_class
{
//data members
//member functions
};
class derived_class1 : visibility_mode base_class
{
//data members
//member functions
};
class derived_class2 : visibility_mode base_class
{
//data members
//member functions
};
Description of the Syntax
visibility mode: It provides the visibility mode in the class declaration. It specifies how the members of the base class will be inherited by the derived class. In the case of Hierarchical Inheritance in C++, it separately defines the visibility mode with every derived class during inheritance.
base class: This is the name of the class from which the derived class inherits its properties and characteristics.
derived class1: This is the name of the first derived class that inherits the properties of the base class using the visibility mode.
derived class2: This is the name of the second derived class that inherits the properties of the base class using the visibility mode.
Note: There can be n number of derived classes of a single base class.
Program 5.6 (Hierarchical inheritance).
// C++ program for Hierarchical Inheritance
#include<iostream>
using namespace std;
class A //superclass A
{
public:
void show_A() {
cout<<"class A"<<endl;
}
};
class B : public A //subclass B
{
public:
void show_B() {
cout<<"class B"<<endl;
}
};
class C : public A //subclass C
{
public:
void show_C() {
cout<<"class C"<<endl;
}
};
int main() {
B b; // b is object of class B
cout<<"calling from B: "<<endl;
b.show_B();
b.show_A();
C c; // c is object of class C
cout<<"calling from C: "<<endl;
c.show_C();
c.show_A();
return 0;
}
The output would be
calling from B:
class B
class A
calling from C:
class C
class A
5.9 Hybrid inheritance
Inheritance is defined as the process in which one class inherits the property of another class. The class whose property is inherited is called as Base class or the parent of that class. The class that inherits the base class’s properties (parent class) is the derived class.
For example, A son inherits the properties of his father. This article will give you a brief introduction to hybrid inheritance and its examples.
Combining various types of inheritance like multiple, simple, and hierarchical inheritance is known as hybrid inheritance.
In simple inheritance, one class is derived from a single class which is its base. In multiple inheritances, a class is derived from two classes, where one of the parents is also a derived class. In hierarchical inheritance, more than one derived class is created from a single base class. Play Video
In hybrid inheritance, there is a combination of one or more inheritance types. For instance, the combination of single and hierarchical inheritance. Therefore, hybrid inheritance is also known as multipath inheritance.
The sports class might look like this
class sports
{
protected:
float score;
public:
void getscore(float);
void putscore();
};
The result will have both the multilevel and multiple inheritance and its declaration would be as follows
class sports: public test, public sports
{
.............
.............
};
where test itself a derived class from student, that is
class test: public student
{
.............
.............
};
Let us take example with both multilevel and multiple inheritance
The following program illustrates the implementation of both multilevel and multiple inheritance.
Program 5.7 (Hybrid inheritance).
#include <iostream>
using namespace std;
class student
{
protected:
int roll;
public:
void getnumber(int a)
{
roll=a;
}
void putnumber()
{
std::cout << "Roll Number : " << roll << "\n";
}
};
class test: public student
{
protected:
float part1,part2;
public:
void getmarks( float x, float y)
{
part1=x;
part2=y;
}
void putmarks()
{
std::cout << "Marks Obtained : " << "\n" << "part1=" << part1 << "\n" << "part2="<< part2 << "\n";
}
};
class sports
{
protected:
float score;
public:
void getscore(float s)
{
score=s;
}
void putscore()
{
std::cout << "Sports weitage : " << score << "\n\n";
}
}; class result: public test, public sports
{
float total;
public:
void display();
};
void result::display()
{
total=part1+part2+score;
putnumber();
putmarks();
putscore();
cout << "Total Score : " << total << "\n";
}
int main()
{
result student1;
student1.getnumber(1234);
student1.getmarks(27.5,33.0);
student1.getscore(6.0);
student1.display();
return 0;
}
The output would be
Roll Number : 1234
Marks Obtained :
part1=27.5
part2=33
Sports weitage : 6
Total Score : 66.5
0 Comments