5

CHAPTER

Functions in C++

C
H
A
P
T
E
R

O
U
T
L
I
N
E
—•    5.1 Introduction
—•    5.2 The main ( ) Function in C and C++
—•    5.3 Parts of Function
—•    5.4 Passing Arguments
—•    5.5 LValues and RValues
—•    5.6 Return by Reference
—•    5.7 Returning More Values by Reference
—•    5.8 Default Arguments
—•    5.9 The const Argument
—•  5.10 Inputting Default Arguments
—•  5.11 Inline Functions
—•  5.12 Function Overloading
—•  5.13 Principles of Function Overloading
—•  5.14 Precautions with Function Overloading
—•  5.15 Library Functions

5.1 INTRODUCTION

When the concept of function or sub-program was not introduced, the programs were large in size and code got repeated as shown in Figure 5.1. It was very difficult to debug and update these large programs because many bugs were encountered. When the functions and sub-programs are introduced, the programs are divided into a number of segments and code duplication is avoided as shown in Figure 5.2. Bugs in small programs can be searched easily and this step leads to the development of complex programs with functions.

One of the features of C/C++ language is that a large sized program can be divided into smaller ones. The smaller programs can be written in the form of functions. The process of dividing a large program into tiny and handy sub-programs and manipulating them independently is known as modular programming. This technique is similar to divide-and-conquer technique. Dividing a large program into smaller functions provides advantages to the programmer. The testing and debugging of a program with functions becomes easier. A function can be called repeatedly based on the application and thus the size of the program can be reduced. The message passing between a caller (calling function) and callee (called function) takes places using arguments. The concept of modular approach of C++ is obtained from function. Following are the advantages of functions:

(a) Support for modular programming

(b) Reduction in program size

(c) Code duplication is avoided

(d) Code reusability is provided

(e) Functions can be called repetitively

(f) A set of functions can be used to form Libraries

images

Fig.5.1 Program without functions

The programs written in C++ like C language are highly dependent on functions. The C++ program is nothing but a combination of one or more functions. Execution of every C++ program starts with user defined function main( ). The method of using functions is slightly changed and enhanced in C++ as compared to C. The C++ language adds a few new features to functions like overloading of functions, default arguments etc. which are described ahead.

Like C, C++ supports two types of functions. They are (1) Library functions, and (2) User defined functions. The library functions can be used in any program by including respective header files. The header files must be included using # include preprocessor directive. For example, a mathematical function uses math.h header file. Various library functions are described at the end of this chapter.

The programmer can also define and use his/her own functions for performing some specific tasks. Such functions are called as user- defined functions. The user-defined functions are those that are defined in a class. They are called as member functions. Various member functions are described further in Chapter 6.

images

Fig.5.2 Program with functions

5.2 THE main( ) FUNCTION IN C AND C++

In C++, the function main( ) always returns integer value to operating system by default. The return value of the function main( ) is used by the operating system to check whether the program is executed successfully or not. If the returned value is zero (0), it means that the program is executed successfully. A non-zero value indicates that the program execution was unsuccessful. The statement return 0 indicates that the program execution is successful. The prototype of main( ) function in C++ follows below:

int main( );

int main(int argc, char *argv[]);

The return statement is used to return value. If there is no return statement, compiler displays a warning message “Function should return a value”. The main( ) function in C and C++ is explained with examples in Table 5.1 below.

Table 5.1 Function main( ) in C and C++

main( ) in C++ main( ) in C
int main ( ) main ( )
{ {
Statement1; Statement1;
Statement2; Statement2;
return 0; }
}  
(a) return type is specified (a) No return type is specified and not necessary.
(b) The return statement is used. (b) No return statement is used.
(c) Can be declared as void. If declared void, no need of return statement. (c) Can be declared as void.

Every function including main( ) by default returns an integer value, hence the keyword int before function main( ) is not compulsory. In C there is no return type to function main( ). The function can be defined as given in Table 5.1.

The function main( ) can be declared as void and return statement can be omitted. But according to ANSI standard the main( ) function should return a value. Thus, the function declared as int main( ) will surely work on any operating system. The function main( ) neither works as inline nor as overloaded. The inline and overloading of functions are illustrated ahead.

5.3 PARTS OF FUNCTION

A function has the following parts:

(a) Function prototype declaration

(b) Definition of a function (function declarator)

(c) Function call

(d) Actual and formal arguments

(e) The return statement?

(1) Function Prototypes

We use many built-in functions. The prototypes of these functions are given in the respective header files. We include them using # include directive. In C++, while defining user-defined functions, it is unavoidable to declare its prototype. A prototype statement helps the compiler to check the return and argument types of the function.

A function prototype declaration consists of the function return type, name, and arguments list. It tells the compiler (a) the name of the function, (b) the type of value returned, and (c) the type and number of arguments.

When the programmer defines the function, the definition of function must be like its prototype declaration. If the programmer makes a mistake, the compiler flags an error message. The function prototype declaration statement is always terminated with semi-colon. The following statements are the examples of function prototypes:

(a) void show (void);

(b) float sum (float, int);

(c) float sum ( float x, int y);

In example (a), the return type is void i.e., the function won't return any value. The void functions are always without return statement. The void argument means that the function won't require any argument. By default every function returns an integer value. To return a non-integer value, the data type should be mentioned in function prototype and definition. While writing the definition of function the return type must be preceded by the function name and it is optional if return type is default (int).

In example (b) the prototype of function sum( ) is declared. Its return type is float and arguments are float and integer type respectively. It is shown in Figure 5.3.

In example (c) with argument type, argument names are also declared. It is optional and also not compulsory to use the same variable name in the program.?

images

Fig.5.3 Parts of function

(2) Function Definition

The first line is called function declarator and is followed by function body. The block of statements followed by function declarator is called as function definition. The declarator and function prototype declaration should match each other. The function body is enclosed with curly braces. The function can be defined anywhere. If the function is defined before its caller, then its prototype declaration is optional.

(3) Function Call

A function is a latent body. It gets activated only when a call to function is invoked. A function must be called by its name, followed by argument list enclosed in parenthesis and terminated by semi-colon.

(4) Actual and Formal Arguments

The arguments declared in caller function and given in the function call are called as actual arguments. The arguments declared in the function declarator are known as formal arguments. For example, Figure 5.4 shows these concepts.

images

Fig.5.4 Actual and formal arguments

As shown in Figure 5.4, variables y and z are actual arguments and j and k are formal arguments. The values of y and z are stored in j and k respectively. The values of actual arguments are assigned to formal arguments. The function uses formal arguments for computing.

(5) The return Statement

The return statement is used to return value to the caller function. The return statement returns only one value at a time. When a return statement is encountered, complier transfers the control of the program to caller function. The syntax of return statement is as follows:

return (variable name); or return variable name;

The parenthesis is optional.

5.1 Write a program to declare prototype of function sum( ). Define the function sum( ) exactly similar to its prototype.

# include <iostream.h>
# include <constream.h>

int main( )
{
   clrscr( );
   float sum(int, float ); // function prototype
   int   a=20;
   float s,b=2.5;
   s=sum(a,b);
   cout <<"Sum=" <<s;
   return 0;
}


float sum (int x, float y)
{
 return (x+y);

}

OUTPUT:
Sum = 22.5

Explanation: In the above program, the prototype of function sum( ) is declared. The prototype instructs the compiler that the function sum( ) should return float value. The types of arguments used by function sum( ) are int and float respectively. The values of variables a and b are passed to function sum( ). These values are assigned to formal arguments x and y. The sum of x and y is calculated and returned. The return value of function is assigned to float variable s.

5.2 Write a program to declare and define void function.

#include <iostream.h>
#include <conio.h>


void main( )
{
clrscr( );

void show(void);
show( );
}


void  show( )
{
   cout <<"
 In show( )";
}

OUTPUT
In show ( )

Explanation: In the above program, the prototype of function show( ) is given preceding void key-word. The statement show( ) invokes the show( ) function that displays the message “In show( )”.

5.4 PASSING ARGUMENTS

The main objective of passing argument to function is message passing. The message passing is also known as communication between two functions i.e., between caller and callee functions. There are three methods by which we can pass values to the function. These methods are.

(a) Call by value (pass by value),

(b) Call by address (pass by address), and

(c) Call by reference (pass by reference).

C++ supports all these three types of passing values to the function whereas C supports only the first two types. The arguments used to send values to function are known as input-arguments. The arguments used to return results are known as output arguments. The arguments used to send as well as return results are known as input-output arguments. While passing values the following conditions should be fulfilled.

The data type and the number of actual and formal arguments should be same both in caller and callee functions. Extra arguments are discarded if they are declared. If the formal arguments are more than the actual arguments then the extra arguments appear as garbage. Any mismatch in the data type will produce the unexpected result.

(1) Pass by Value

In this type, value of actual argument is passed to the formal argument and operation is done on the formal arguments. Any change in the formal argument does not effect the actual argument because formal arguments are photocopy of actual arguments. Hence, when function is called by call by value method, it does not affect the actual contents of actual arguments. Changes made in the formal arguments are local to the block of called function. Once control returns back to the calling function the changes made vanish. The following example illustrates the use of call by value:

5.3 Write a program to demonstrate call by value.

# include <iostream.h>
# include <constream.h>
void main( )
{
   clrscr( );
   int x,y;
   void change(int , int);
   cout<<"
 Enter Values of X & Y :";
   cin>>x>>y;
   change(x,y);
   cout <<"

 In function main ( ) ";
   cout<<"
 Values  X="<<x <<" and  Y= "<<y;
   cout<<"
 Address X="<<(unsigned)&x <<" and  Y= "<<(unsigned)&y;
}


void change(int a, int b)
{
   int k;  k=a;  a=b;  b=k;
   cout <<"
 In function change ( ) ";
   cout<<"
 Values  X="<<a <<" and  Y= "<<b;
   cout<<"
 Address X="<<(unsigned)&a <<" and  Y= "<<(unsigned)&b;

}

OUTPUT

Enter Values of X & Y :5 4

In function change( )
Values X=4 and Y= 5
Address X=4090 and Y= 4092

In function main( )
Values X=5 and Y= 4
Address X=4096 and Y= 4094

Explanation: In the above program, we are passing values of actual arguments x and y to function change( ). The formal arguments a and b of function change( ) receive these values. The values are exchanged i.e., value of a is assigned to b and vice versa. They are displayed on the screen. When the control returns back to the main( ), the changes made in function change( ) vanish because a and b are local variables of function change( ). In the main( ) the values of x and y are printed as they are read from the keyboard. In call by value method, the formal argument acts as duplicate of the actual argument. The addresses of actual and formal arguments are different. Thus, changes made with the variables are temporary.

(2) Pass by Address

In this type, instead of passing values, addresses are passed. Function operates on addresses rather than values. Here the formal arguments are pointers to the actual arguments. Hence changes made in the arguments are permanent. The following example illustrates passing the arguments to the function by pass by address method.

5.4 Write a program to demonstrate pass by address.

# include <iostream.h>
# include <constream.h>


void main( )
{
   clrscr( );
   int x,y;
   void change(int* , int*);
   cout<<"
 Enter Values of X & Y :";
   cin>>x>>y;
   change(&x,&y);
   cout <<"
 In main( )";
   cout <<"
 Values    X="<<x <<" and  Y="<<y;
   cout <<"
 Addresses X="<<(unsigned)&x <<" and  Y="<<(unsigned)&y;
}
void change(int *a, int *b)
{
   int *k;
   *k=*a;
   *a=*b;
   *b=*k;
   cout <<"
 In change( )";
   cout <<"
 Values    X="<<*a <<" and  Y="<<*b;
   cout <<"
 Addresses X="<<(unsigned)a <<" and  Y="<<(unsigned)b;
}

OUTPUT

Enter Values of X & Y :5 4

In change( )

Values X=4 and Y=5
Addresses X=4096 and Y=4094

In main( )

Values X=4 and Y=5

Addresses X=4096 and Y=4094

Explanation: In the above example, we are passing addresses of actual arguments to the function change( ). The formal arguments are declared as pointers in the function declarator of change ( ). The formal arguments receive addresses of actual arguments i.e., formal arguments point to the actual argument. Here the change( ) function operates on the addresses of actual argument through pointers. The addresses of actual arguments and formal arguments are same. Hence, the changes made in the values are permanent.

(3) Passsing by Reference

C passes arguments by value and address. In C++ it is possible to pass arguments by value, address and reference. C++ reference types, declared with & operator are nearly identical but not exactly same to pointer types. They declare aliases for object variables and allow the programmer to pass arguments by reference to functions. The reference decelerator (&) can be used to declare references outside functions.

   int k = 0;

   int &kk = k; // kk is an alias for k
   kk = 2; // same effect as k = 2

This creates the lvalue kk as an alias (assumed name) for k, provided that the initializer is the same type as the reference. Any operation on kk will give the same result as operations on k.

Example

     Kk = 5 // assigns 5 to k and

     &kk // returns the address of k.

   The reference decelerator can also be used to declare reference type parameters
   within a function.

void funcA (int i);

void funcB (int &kk); // kk is type “reference to int”
 

int s=4;

funcA(s); // s passed by value

funcB(s); // s passed by reference

The s argument passed by reference can be modified directly by funcB whereas, funcA receives a duplicate copy (not actual) of the s argument (passed by value). Due to this reason variable s itself cannot be modified by funcA. When an actual variable s is not appearing in the above example, argument s is passed by value, the matching formal argument in the function obtains a copy of s. Any alteration to this copy inside the scope of the function body are not thrown back in the value of s itself. Absolutely, the function can return a value that could be used later to change s, but the function cannot directly alter a parameter passed by value. The conventional C method for changing s operates on the address of actual argument (&s), the address of s, rather than s itself. Although &s is passed by value, the function can access s through the copy of &s it receives. Even though the function does not need to alter s, it is still useful (though subject possibly to risky secondary results) to pass &s, especially if s is a large data structure. Passing s directly by value contains the useless copying of the data structure.

5.5 Write a program to pass the value of variable by value, reference, and address and display the result.

# include <iostream.h>
# include <conio.h>
# include <process.h>


void main( )
{
clrscr( );
void funA(int s);
void funB(int & );
void funC(int *);


int s=4;             // initial value
funA(s);             // s passed by value
cout <<"
Value of s= "<<s  <<" Addresss of s : "<<unsigned(&s);
funB(s);             // s passed by reference
cout <<"
Value of s= "<<s  <<" Addresss of s : "<<unsigned(&s);
funC(&s);            // s passed by reference (C style )
cout <<"
Value of s= "<<s  <<" Addresss of s : "<<unsigned(&s);
}


void funA( int i)
{i++;  }


void funB(int &k)
{
  k++;


 }
void  funC(int *j) { ++*j; }

OUTPUT

Value of s= 4 Addresss of s : 4096
Value of s= 5 Addresss of s : 4096
Value of s= 6 Addresss of s : 4096?

Explanation: In the above example, funA( ), funB( ) and funC( ) i.e., three functions are declared. The integer variable s is declared and initialized to 4. The funA( ) is invoked and value of s is passed by value. In function funA( ) the value of s is incremented. After execution of funA( ) the value of s is printed in main( ) which is same as previous one. Thus, passing variable by value cannot change the contents of the variable.

The value of s is again passed to funB( ). The function funB( ) receives the value of s by reference. The value of s is received by variable k by reference i.e., variable k is an alias for variable s and both have the same memory location. The variable k is incremented. Thus, any change made in reference variable effects the actual variable. Thus, after execution of funB( ) the printed value of s is equal to 5.

images

Fig.5.5 Argument passing methods

The third function, funC( ) uses conventional C style. Here, address of the variable s is passed to funC( ). The formal argument * j is pointer to the actual argument. Thus, any change made through pointer j also reflects on the actual variable. Thus, we can change the value of variable using call by reference. Figure 5.5 explains the methods of passing arguments to function.

In function declarator and function prototype declaration the formal arguments are preceded by & operator. The reference type variable can be used in the same manner like other ordinary variables. The following points related to reference parameters are given below:

(a) A reference may not be null. It should always refer to a legal variable.

(b) Once declared, a reference should not be altered to referrer to another object.

(c) A reference variable does not need any explicit address manipulation to access the actual value of the variable.

5.5 LVALUES AND RVALUES

(1) Lvalues (Left values)

A lvalue is an object locator. It is an expression that points to an object. An example of an lvalue expression is *k which results to a non-null pointer. A changeable lvalue is an identifier or expression that is related to an object that can be accessed and suitably modified in computer memory. A const pointer to a constant is not a changeable lvalue. A pointer to a constant can be altered (not its dereferenced value). A lvalue could suitably stand on the left (the assignment side) of an assignment statement. Now, only changeable lvalue can legally stand on the left of an assignment statement. For example, suppose x and y are non-constant integer identifiers with appropriate allocated memory. Their lvalues are changeable. The following expressions are legal:

X = 1;

Y = x + y are legal expressions.

(2) Rvalues (Right values)

The statement x + y is not a lvalue. x + y = z is invalid because the expression on the left is not related to a variable. Such expressions are often called rvalues.

5.6 RETURN BY REFERENCE

We have studied the reference variable and it's functioning. A reference allows creating alias for the preexisting variable. A reference can also be returned by the function. A function that returns reference variable is in fact an alias for referred variable. This technique of returning reference is used to establish cascade of member functions calls in operator overloading. Consider the following example:

The program given below illustrates return by reference.

5.6 Write a program to return a value by reference.

# include <iostream.h>
# include <constream.h>


void main( )
{
   clrscr( );
   int & min ( int &j, int &k);
   int a=18,b=11,c;
   c=min (a,b);
   cout <<"Minimum Value = "<<c;
   }


   int & min(int &j, int &k)
   {
   if  (k<j ) return k;
   else
   return j;
   }

OUTPUT

Minimum Value = 11

Explanation: In the above program, the statement int & min (int &j, int &k) declares prototype of function min( ). The & reference operator is used because the function returns reference to int and also receives arguments as reference. The function min( ) receives two integers as reference and returns minimum value out of two by reference.

5.7 Write a program to demonstrate return by reference.

# include <iostream.h>
# include <constream.h>



int & large( int & p, int & q);


void main ( )
{  clrscr( );
   int l,k;
   cout <<"
 Enter values of l and k : ";
   cin>>l>>k;
   large(l,k)=120;
   cout <<" l= "<<l << " k="<<k;
}


   int & large(int & p, int & q)
   {
       if (p>q) return p;
       else return q;
   }

OUTPUT

Enter values of l and k : 48
l=4 k=120

Enter values of l and k : 92
l= 120 k=2

Explanation: In function main( ), the statement large (l, k)=120; calls the function large( ). It returns reference to the variable containing larger value and assigns the value 120 to it. The return type of function large( ) is int & (reference), it indicates that the call to function large( ) can be written on the left side of the assignment operator. Consequently, the statement large (l,k)=120; is legal and assigns 120 to the variable containing larger value.

5.7 RETURNING MORE VALUES BY REFERENCE

The return( ) statement has one big limitation that it can return only one value at a time. The return( ) statement is only used when values are passed by value to functions. Call by address and call by reference, accesses memory location directly. When the user wants to return more than one value from function, he/she should pass values by address or by reference method. In C, for returning more values, call by address is used. In C++ we have one additional method i.e., call by reference. Consider the following program:

5.8 Write a program to return more than one value from function by reference.

# include <iostream.h>
# include <constream.h>


void main( )
{

   int sq,cb,n;
   void more(int &, int &, int);
   cout <<"
 Enter a Number : ";
   cin>>n;
   more(sq,cb,n);
   cout <<"
 Square ="<<sq;
   cout <<"
 Cube   ="<<cb;
}


void more(int & s, int & c,int j)
{
   s=j*j;
   c=j*j*j;
}

OUTPUT
Enter a Number : 2

Square =4
Cube =8

Explanation: In the above program, the function more( ) is used to perform square and cube of an integer passed. The three variables sq, cb and n of integer type are declared. The number entered by the user is stored in variable n. The variables sq, cb and n are passed to function more( ).

In function more( ), s and j are reference variables and j is a local variable of function more( ). The variable s is reference variable of sq and variable c is reference variable of cb. The variables s and sq and c and cb have the same memory locations. Thus, any value assigned to s and c can be accessed by sq and cb. The variable s is assigned the square of j (n) and variable cb is assigned with cube of j (n).

5.8 DEFAULT ARGUMENTS

Usually, a function is called with all the arguments as declared in function prototype declaration and function definition. C++ compiler lets the programmer to assign default values in the function prototype declaration/function declarator of the function. When the function is called with less parameter or without parameters, the default values are used for the operations.

It is not allowed to assign default value to any variable, which is in between the variable list. Variables lacking default values are written first, followed by the variables containing default values. This is because the convention of storing variables on the stack in C++ is from right to left.

The default values can be specified in function prototype declaration or function declarator. Normally, the default values are placed in function prototype declaration. In case the function is defined before caller function, then there is no need to declare function prototype. Hence, the default arguments are placed in function declarator. The compiler checks for the default values in function prototype and function declarator and provides these values to those arguments that are omitted in function call.

The default arguments are useful while making a function call if we do not want to take effort for passing arguments that are always same. It is also useful when we update an old function by adding more arguments in it. Using default arguments, the function calls can continue to use previous arguments with the new arguments.

The example given below declares the default arguments.

Example

(a)int sum (int a,int b=10 ,int c = 15,int d=20)

In this example, function sum( ) has four arguments. They are a, b, c and d of integer types. The variable b, c, and d are initialized with 10, 15 and 20 respectively. These values are used when the function sum( ) is called with fewer arguments.

5.9 Write a program to define function sum( ) with default arguments.

# include <iostream.h>
# include <conio.h>


int main( )
{
   clrscr( );
   int sum (int a,int b=10 ,int c=15,int d=20 ); // Function prototype


       int  a=2;
       int  b=3;
       int  c=4;
       int  d=5;


cout <<"Sum=" <<sum(a,b,c,d);
cout <<"
Sum=" <<sum(a,b,c);
cout <<"
Sum=" <<sum(a,b);
cout <<"
Sum=" <<sum(a);
cout <<"
Sum=" <<sum(b,c,d);


return 0;
}


   sum (int j, int k, int l, int m)
{
return (j+k+l+m);
}

OUTPUT:

Sum=14
Sum=29
Sum=40
Sum=47
Sum=32

Explanation: In the above example, the prototype of variable sum( ) is declared. The function sum( ) has four arguments of integer types a, b, c and d. The variable b, c and d are initialized with default values 10, 15 and 20 respectively in function prototype declaration. The variable a is not initialized. The function sum( ) is called five times. Each time the resultant sum has different values.

In the first cout statement, the function sum( ) is called with four arguments. In this function call, no default values are used i.e., actual values of variables initialized are considered. Hence, the result is 14.

In the second cout statement, the function sum( ) is called with three arguments (one less argument). In this function call, actual values of starting three variables a, b, c and default value of the fourth variable d are considered. Hence, the result is 29.

In the third cout statement, the function sum( ) is called with two arguments (two arguments less). In this function call, actual values of starting two variables a, b and default values of last two variables c, d is considered. Hence, the result is 40.

In the fourth cout statement, the function sum( ) is called with one argument. In this function call, the actual value of variable a and default values of variables b, c and d i.e., 10, 15 and 20 respectively, are taken into account. The result displayed is 47.

In the last cout statement, the function sum( ) is called with last three arguments. The actual values of b, c, and d variables are 3,4 and 5 and last default value 20 is together taken into account. Hence the result is 32.

5.10 Write a program to find the area of a triangle by using default values and actual values. The formula for area of a triangle is ½ * base * height.

# include <iostream.h>
# include <conio.h>


int main( )
{


clrscr( );


float area(int base=3,int height=5 ); // Function prototype


int base=2;

int height=7;
cout <<"Area of Triangle : "  << area(base,height);
cout <<"
Area of Triangle : "  << area (base);
cout <<"
Area of Triangle : " <<area(height);
return 0;
}


float area( int j, int k)
{ return (.5*j*k); }

OUTPUT:
Area of Triangle : 7
Area of Triangle : 5
Area of Triangle : 17.5

Explanation: In the above program, the prototype of function area( ) is declared with two default values 3 and 5 for variables base and height respectively. In function main( ) the variable base and height are defined and initialized with 2 and 7 respectively. In the first call of the function area( ), function is called with both the arguments i.e., base and height. In this call no default arguments are used. In the second call the function area( ) is called with one argument (one less argument). In this call, one actual and one default value is used. The third call is the same as the second one.

5.9 THE const ARGUMENT

The constant variable can be declared using const keyword. The const keyword makes variable value stable. The constant variable should be initialized while declaring.

Syntax:

(a) const <variable name> = <value>;

(b) <function name> (const <type>*<variable name>;)

(c) int const x // in valid

(d) int const x =5 // valid

In statement (a), the const modifier assigns an initial value to a variable that cannot be changed later by the program.
For example,

const age = 40;

Any attempt to change the contents of const variable age will produce a compiler error. Using pointer, one can indirectly modify a const variable as shown below:

*(int *)&age = 45;

When the const variable is used with a pointer argument in a function's parameter list, the function cannot modify the variable that the pointer points to. For example,

int cube (const int *x, ...);
       Here the cube function is prohibited from altering the integer variable.

5.10 INPUTTING DEFAULT ARGUMENTS

Default arguments are used when function is invoked with fewer arguments than declared. The default values are placed in function prototype or function declarator. It is also possible to directly invoke user-defined function in function prototype or function declarator. The return value of function is considered as default value. The following program illustrates this point:

5.11 Write a program to enter default values using function.

# include <iostream.h>
# include <constream.h>

void main( )
{
   clrscr( );
   int input(void);
   void display ( int = input( ) );


   display(20);  // first call with argument
   display( );  //  second call with default argument


}


void display( int j)
{
   cout <<"
Integer is : "<<j;
}


input( )
{
   int k;
   cout <<"
 Enter an integer : ";
   cin >>k;
   return k;
}

OUTPUT
Integer is : 20
Enter an integer : 12
Integer is : 12

Explanation: In the above program, user-defined functions display( ) and input( ) are declared and defined. The display( ) function is used to display passed integer on the screen. The input( ) function when executed asks for an integer. The function input( ) is used as default value for function display( ). When a function display( ) is invoked without argument, the input( ) function assigned as default argument in function prototype is executed. User enters a number. Entered number is passed to display( ) function and displayed on the screen.

5.11 INLINE FUNCTIONS

One of the prime factors behind using function is that code duplication in program is avoided and memory space is saved. When a function is defined and invoked, one set of instruction is created in the memory of the system. At each call, the control passes to the subroutine at a specified address in the memory. The CPU stores the memory address of instruction following the function calls into the stack and also pushes the arguments in the stack area. The compiler runs the function, stores the return values in a memory location or register and when execution completes, the control returns to the calling function. After this, execution resumes immediately to the next line following the function call statement. If the same function is called several times, each time the control is passed to the function i.e., the compiler uses the same set of instructions at each call. Due to this passing of control in between caller and callee functions, execution speed of program decreases. By preventing repetitive calls, program execution speed can be increased.

The C++ provides a mechanism called inline function. When a function is declared as inline, the compiler copies the code of the function in the calling function i.e., function body is inserted in place of function call during compilation. Passing of control between caller and callee functions is avoided. If the function is very large, in such a case inline function is not used because the compiler copies the contents in the called function that reduces the program execution speed. The inline function is mostly useful when calling function is small. It is advisable to use the inline function for only small functions.

Inline mechanism increases execution performance in terms of speed. The overhead of repetitive function calls and returning values are removed. On the other hand, the program using inline functions needs more memory space since the inline functions are copied at every point where the function is invoked.

For defining an inline function, the inline keyword is preceded by the function name. The inline functions are declared below:

inline function - name 
{
statement1;
statement2; // Function body
}

Example:

inline float square ( float k)
{
   return ( k*k);
}

The above example can be executed as given below:

j=square (2.5);

k=square (1.1+1.4);

After the execution of above statements, the values of j and k will be 6.25. The inline keyword just makes an appeal to the compiler. The compiler may neglect this request if the function defined is too big in size or too convoluted. In such a case the function is treated as normal function.

Following are some situations where inline function may not work:

(1) The function should not be recursive.

(2) Function should not contain static variables.

(3) Function containing control structure statements such as switch, if, for loop etc.

(4) The function main( ) cannot work as inline.

The inline functions are similar to macros of C. The main limitation with macros is that they are not functions and errors are not checked at the time of compilation. The function offers better type testing and do not contain side effects as present in macros. Consider the following example:

5.12 Write a program to calculate square using inline function and macro.

# include <iostream.h>
# include <constream.h>


# define SQUARE(v) v * v


inline float square( float j)
{
   return (j*j);
}


void main( )
{
   clrscr( );
   int  p=3, q=3,r,s;
   r=SQUARE(++p);
   s=square(++q);
   cout <<" r= "<<r<<"
"<<" s= "<<s;
}

OUTPUT
r= 25
s= 16

Explanation: In the above program, the function square( ) is declared as inline function. The macro SQUARE( ) expanded into r=++v *++v. The variable p is incremented only once but in macros expansion it is incremented twice. Therefore, it gives wrong result.

5.13 Write a program to define function cube( ) as inline for calculating cube.

# include <iostream.h>
# include <constream.h>


void main( )
{
   clrscr( );
   int cube(int);
   int j,k,v=5;
   j = cube(3) ;
   k = cube(v);


   cout <<"
 Cube of j="<<j;
   cout <<"
 Cube of k="<<k;
}


inline int cube(int h)
{
   return (h*h*h);
}

OUTPUT

Cube of j=27
Cube ofk=125

Explanation: In the above program, the function cube( ) is declared as inline. The function cube( ) calculates cube of passed number. The function is declared as inline i.e., the statements of function cube( ) are inserted at the point of function call as shown in Figure 5.6.

5.12 FUNCTION OVERLOADING

It is possible in C++ to use the same function name for a number of times for different intentions. Defining multiple functions with same name is known as function overloading or function polymorphism. Polymorphism means one function having many forms. The overloaded function must be different in its argument list and with different data types. The examples of overloaded functions are given below. All the functions defined should be equivalent to their prototypes.

int sqr (int);

float sqr (float);

long sqr (long);

5.14 Write a program to calculate square of an integer and float number. Define function sqr( ). Use function-overloading concept.

# include <iostream.h>
# include <conio.h>


int sqr(int);
float sqr(float);


main( )
{
   clrscr( );
   int a=15;
   float b=2.5;
   cout <<"Square = "<<sqr(a) <<"
";
   cout <<"Square = "<< sqr(b) <<"
";
   return 0 ;
}


int sqr(int s)
{
   return (s*s);
}


float sqr (float j)
{
   return (j*j);
}

OUTPUT Square = 225
Square =6.25

Explanation: In the above program, the function sqr( ) is overloaded for integer and float. In the first call of the function sqr( ), an integer 15 is passed. The compiler executed integer version of the function and returns result 225. In the second call, a float value 2.5 is passed to function sqr( ). In this call, the compiler executed the float version of the function and returns the result 6.25. The selection of function to execute is made at run- time by the compiler according to the data type of variable passed.

5.15 Write a program to find the area of rectangle, triangle and sphere. Use function overloading.

#include<iostream.h>
#include<constream.h>
#define pi 3.142857142857142857
int calcarea(int length,int breadth);
float calcarea(double base,double height);
float calcarea(double radius);


void main( )
   {
      int area1;
      float area2;
      double area3;
      area1=calcarea(10,20);
      area2=calcarea(4.5,2.1);
      area3=calcarea(3.12145);
      clrscr( );
      cout<<"Area of rectangle is  : "<<area1<<endl;
      cout<<"Area of traingle is  : "<<area2<<endl;
      cout<<"Area of sphere is   : "<<area3<<endl;
      getch( );
   }
      int calcarea(int length,int breadth)
   {
      return (length*breadth);
   }
      float calcarea(double base,double height)
   {


      return ((0.5)*base*height);
   }
      float calcarea(double radius)
   {
      return ((4/3)*pi*radius*radius*radius);
   }

OUTPUT:
Area of rectangle is : 200
Area of traingle is : 4.725
Area of sphere is : 95.58589

Explanation: In the above program, function calcarea( ) is overloaded. It is used for finding the area of a rectangle, triangle and sphere. Explanation is same as the previous problem.

5.13 PRINCIPLES OF FUNCTION OVERLOADING

(1) If two functions have the similar type and number of arguments (data type), the function cannot be overloaded. The return type may be similar or void, but argument data type or number of arguments must be different. For example,

(a) sum (int,int,int);
 sum (int,int);

Here, the above function can be overloaded. Though data type of arguments in both the functions are similar but number of arguments are different.

(b) sum (int,int,int);
 sum (float,float,float);

      In the above example, number of arguments in both the functions are same, but data types are different. Hence, the above function can be overloaded.

(2) Passing constant values directly instead of variables also result in ambiguity. For example,
int sum (int,int);
float sum (float float float);
Here, sum( ) is an overloaded function for integer and float values. If values are passed as follows
sum (2,3);
sum (1.1,2.3,4.3);
the compiler will flag an error because the compiler cannot distinguish between these two functions. Here, internal conversion of float to int is possible. Hence, in both the above calls integer version of function sum( ) is executed. To overcome this problem, the user needs to do following things:

    (i) Declare prototype declaration of all the overloaded functions before function main( ).

       (ii) Passing argument-using variables as follows:
   sum (a,b) ; // a and b are integer variables
   sum (e,r,t,y); // e,r,t and y are float variables

      Refer to program 5.22 for confirmation. Also try this program with direct values and by declaring function prototype inside main ( ).

(3) The compiler attempts to find an accurate function definition that matches in types and number of arguments and invokes that function. The arguments passed are checked with all declared functions. If matching function is found then that function gets executed.

(4) If there is no accurate match found, compiler makes the implicit conversion of actual argument. For example, char is converted to int and float is converted to double. If all above steps fail then compiler performs user built functions.

The following example illustrates this point.

5.16 Write a program to overload a function and create a situation such that the compiler does integral conversion.

# include <iostream.h>
# include <conio.h>
   int sqr (int);
   float  sqr (double );


main( )
{
   clrscr( );
   int a=15;
   float b=3.5;
   cout <<"Square = "<<sqr('A') <<"
";
   cout <<"Square = "<< sqr(b) <<"
";
   return 0 ;
}


int sqr (int s) { return (s*s); }
float  sqr (double  j) { return (j*j);  }

OUTPUT

Square = 4225
Square = 12.25

Explanation: In the above program, the function square is overloaded. The first prototype of function sqr(int) is proposed for integer variable and second for double variable. In function main( ), the ‘A’ character data type value is passed to the function sqr( ). The compiler invokes the integer version of the function sqr( ) because the char data type is compatible with integer. In the second call, a float value is passed to the function sqr( ). This time the compiler invokes the double data type version of function sqr( ).

When accurate match is not found the compiler makes internal conversion as seen in the above example. C++ automatically attempts to convert the arguments used to call a function into the type of arguments expected by the function.

(5) If internal conversion fails user-defined conversion is carried out with implicit conversion and integral promotion. The user-defined conversion is used with class objects.

(6) Sometime while making internal conversion, ambiguity is created if one data type is compatible with two or more data types. If such situation occurs, the compiler displays an error message.
Consider the following example. Given below are two versions of sqr( ) function, one is for long data type and other for double data type.
long sqr ( long);
double sqr (double);
sqr (10); // function call

If an integer value is passed to the function sqr( ), the compiler will fall in confusion about the version to be executed and will result in an error message “Ambiguity between ‘sqr(long)’ and ‘sqr(double)’”.

(7) If a programs has two versions of functions i.e., one for float and second for double data type, then if we pass a float number, the double version of function is selected for execution. But the same is not applicable with integer and long integer.

5.17 Write a program to define overloaded function add( ) for integer and float and perform the addition.

# include <iostream.h>
# include <conio.h>


   int add (int , int, int);
   float add ( float , float , float);


   int main( )
   {
   clrscr( );
   float fa,fb,fc,fd;
   int   ia,ib,ic,id;


cout <<"
 Enter values integer values for ia,ib and ic : ";
   cin >>ia >>ib >>ic;
   cout <<"
 Enter float values for fa,fb and fc : ";
   cin >>fa >>fb >>fc;
   id=add (ia,ib,ic);
cout <<"
 Addition : " <<id;
   fd=  add (fa,fb,fc);
cout <<"
 Addition : "<<fd;
   return 0;
   }
add ( int j, int k, int l) {  return (j+k+l); }
float add (float a, float  b, float c ) { return (a+b+c);}

OUTPUT
Enter values integer values for ia,ib and ic : 1 2 4

Enter float values for fa,fb and fc : 2.2 3.1 4.5

Addition : 7
Addition : 9.8

Explanation: In the above program, two versions of function add( ) are declared. One for integer values and second for float values. Three integer and float values are entered through the keyboard. According to the data type the compiler executes appropriate function. The prototype of functions should be written before main( ) function. If we write the prototype inside the main( ), the float version of the function will not be executed.

5.18 Write a program to define overloaded function. Invoke the overloaded function through another overloaded function.

# include <iostream.h>
# include <conio.h>

   int add (void);
   float add ( float , float , float);

   float fa,fb,fc,fd;
   int id;

   int main( )
   {

   clrscr( );
   cout <<"
 Enter float values for fa,fb and fc : ";
   cin >>fa >>fb >>fc;
   id=add ( );
   cout <<"
 Addition : " <<id;
   fd=  add (fa,fb,fc);
cout <<"
 Addition : "<<fd;

   return 0;

   }

add ( )
{
int x;
x=add(fa,fb,fc);
return (x);
}

float add (float a, float  b, float c ) { return (a+b+c);}

OUTPUT

Enter float values for fa,fb and fc : 5.5 2.4 8.2
Addition : 16
Addition : 16.1

Explanation: In the above program, the function add( ) is overloaded. The add(void) function won't require any argument but returns integer. The float add( ) function requires three arguments of float type. Here, the arguments are fa, fb, fc, fd and id and are declared as global so that any function can call them. After entering three float values, the add(void) function is called. The add(void) function calls the float type of add( ), the float type add( ) function calculates addition and returns results to function add(void). The add(void) function returns addition as an integer. In the second call, the compiler calls the float add( ) function. This function returns addition of float values.

5.14 PRECAUTIONS WITH FUNCTION OVERLOADING

Function overloading is a powerful feature of C++. But, this facility should not be overused. Otherwise it becomes an additional overhead in terms of readability and maintenance. Following precautions must be taken:

(1) Only those functions that basically do the same task, on different sets of data, should be overloaded. The overloading of function with identical name but for different purposes should be avoided.

(2) In function overloading, more than one function has to be actually defined and each of these occupy memory.

(3) Instead of function overloading, using default arguments may make more sense and fewer overheads.

(4) Declare function prototypes before main( ) and pass variables instead of passing constant directly. This will avoid ambiguity that frequently occurs while overloading functions.

5.15 LIBRARY FUNCTIONS

(a) ceil, ceill and floor, floorl

The functions ceil and ceill round up the given float number. Where as the functions floor and floorl round down the float number. They are defined in math.h header file. Their declarations are given below:

Declaration
   double ceil (double n);
   double floor (double n);
   long double ceill (long double (n));
   long double floorl (long double (n));

The given below program illustrates the working of these functions.

5.19 Write a program to round down and up the given float number.

#include <math.h>
#include <iostream.h>
# include <conio.h>


void  main(void)
{
   clrscr( );
   float num = 3.12;
   float  d, u;


   d = floor(num);
   u = ceil(num);


cout <<"
 Original number     is : "<<num;
cout <<"
 Number rounded up   is : "<<u;
cout <<"
 Number rounded down is : " <<d;
   }

OUTPUT

Original number is : 3.12
Number rounded up is : 4
Number rounded down is : 3

Explanation: In the above program, the float variable num has a value 3.12. The floor( ) function converts it to the nearest and small integer number than variable num and returns it to variable d where as the ceil( ) function converts the float number to the nearest and greater number than num.

(b) Modf and modfl

The function modf breaks double into integer and fraction elements and the function modfl breaks long double into integer and fraction elements. These functions return the fractional elements of given number. They are declared as given below:

Declaration
    double modf (double n, double *ip);
    long double modfl (long double (n), long double *(ip));

5.20 Write a program to separate double number into integer and fractional parts.

#include <math.h>
# include <conio.h>
# include <iostream.h>


int main( )
{
   clrscr( );
   double   f, i;
   double  num = 211.57;


   f = modf(num, &i);
cout <<"
 The Complete Number   : "<<num;
cout <<"
 The Integer  elements : "<<i;
   cout <<"
 Fractional   Elements : "<<f;


   return 0;
}

OUTPUT

The Complete Number : 211.57
The Integer elements : 211
Fractional Elements : 0.57

Explanation: In the above program, the function modf ( ) separates a double number into separate integer and fractional parts. The second argument of the function is passed by reference that after execution holds the integer part of the number.
(c) abs, fabs and labs

The function abs( ) returns the absolute value of an integer. The fabs( ) returns the absolute value of a floating point number and labs( ) returns the absolute value of a long number.

Declaration:
   Int abs (int n);
   double fabs (double n);
   long int labs (long int n);
    If abs is invoked using STDLIB.H, it is executed as a macro that expands to inline code. If we need to use the original abs function then undefine the macro using statement #undef abs in the program, after #include <stdlib.h>.
(d) norm
    This function is defined in complex.h header file and it is used to calculate the square of the absolute value.
Syntax: double norm(complex n);

5.21 Write a program to calculate the square of the complex number using norm( ) function.

# include <iostream.h>
# include <complex.h>
# include <conio.h>
int main ( )
{
   clrscr( );
   double x=-12.5;
   cout <<norm(x);
   return 0;
}

OUTPUT
6.25

Explanation: In the above program, the norm( ) function calculates the square of complex negative number.

(e) complex( ), real( ), imag( ) and conj( )

Complex( ): This function is defined in complex.h header file and it creates complex numbers. Creates a complex number from given real and imaginary parts. The imaginary part is supposed to be 0 if not given. Complex is the constructor for the C++ class complex. This function returns the complex number with the given real and imaginary parts.

Real( ) : Returns real part of the complex number.
Imag( ) : Returns the imaginary part of the complex number.
Conj( ) : Returns complex conjugate of a complex number.
Syntax: complex complex(double real, double imag);
Syntax: double real( complex x);
Syntax: double imag( complex x);
Syntax : double conj( complex x);

5.22 Write a program to return real, imaginary part and conjugate number.

# include <conio.h>
#include <iostream.h>
#include <complex.h>


int main(void)
{
    double a = 4.5, b = 7.4;
    clrscr( );
    complex c = complex(a,b);


   cout << "c = "<< c << "
";


   cout << " and imaginary real part = " << imag(c) << "
";


   cout << "c has complex conjugate =  " << conj(c) << " 
";
   return 0;
}

OUTPUT
C = (4.5, 7.4)
and imaginary real part = 7.4
c has complex conjugate = (4.5, -7.4)

Explanation: In the above program, variable a and b of double data type are declared and initialized with 4.5 and 7.4. By applying the complex( ), imag( ) and conj( ) functions, results are obtained. The results are shown in the output.

SUMMARY

(1) The programs written in C++ like C language, highly depends on functions. The C++ program is nothing but a combination of one or more functions.

(2) In C++, the function main( ) always returns an integer value to the operating system. The return value of the function main( ) is used by the operating system to check whether the program is executed successfully or not.

(3) A function prototype declaration consists of function's return type, name, and arguments list. When the programmer defines the function, the definition of function must be same like its prototype declaration.

(4) In C++ it is possible to pass arguments by value or by reference. C++ reference type is declared with & operator and it is nearly identical but not exactly same as pointer types. They declare aliases for objects variables and allow the programmer to pass arguments by reference to functions.

(5) An lvalue is an object locator and an expression that indicates an object.

(6) The statement x + y is not an lvalue, x + y = z is invalid because the expression on the left is not related to a variable. Such expressions are often called rvalues.

(7) C++ lets the programmer to assign default values in the function prototype declaration of the function. When the function is called with lesser parameters then the default values are used for the operations.

(8) The constant variable can be declared using const keyword. The const keyword makes variable value stable. The constant variable should be initialized at the time of declaration.

(9) The C++ provides a mechanism called inline function. When a function is declared as inline the compiler copies the code of the function in the calling function.

(10) C++ makes it possible for the programmer to use the same function name for various times for different intentions. This is called as function overloading or function polymorphism.

(11) The function modf( ) breaks double into integer and fraction elements and the function modfl( ) breaks long double into integer and fraction elements.

(12) The functions ceil( ) and ceill( ) round up the given float number where as the functions floor( ) and floorl( ) round down the float number.

(13) The function abs( ) returns the absolute value of an integer. The fabs( ) returns the absolute value of a floating point number and labs( ) returns the absolute value of a long number

EXERCISES

[A] Answer the following questions.

(1) What are the differences between C and C++ functions?

(2) Describe different parts of a function?

(3) What are void functions?

(4) What does function prototype mean? Is it compulsory?

(5) When is function prototype declaration not necessary?

(6) What are default arguments?

(7) Where are default arguments assigned?

(8) How are default arguments entered at run- time?

(9) What are inline functions? Discuss its advantages and disadvantages.

(10) What are the rvalue and lvalue in an expression? Explain with examples.

(11) What is the difference between call by value and call by reference? Illustrate them with examples.

(12) What are constant arguments?

(13) How is the value of a constant variable changed?

(14) What is function overloading?

(15) What are the rules for defining overloaded functions?

(16) What precautions should we take while overloading function?

(17) What is the difference between pointer and reference variable?

(18) What is the difference between normal function and inline function?

(19) What are actual and formal arguments?

(20) How does return statement pass more than one value from function?

[B] Answer the following by selecting the appropriate option.

(1) The main( ) function returns an integer value to

(a) operating system

(b) compiler

(c) main( ) function

(d) none of the above

(2) The concept of declaring same function name with multiple definitions is

(a) function overloading

(b) operating overloading

(c) both (a) and (b)

(d) none of the above

(3) The default arguments are used when

(a) function is called with less arguments

(b) function is void

(c) when arguments are passed by reference

(d) none of the above

(4) The constant function

(a) cannot alter values of a variable

(b) can alter values of a constant variable

(c) makes its local variable constant

(d) none of the above

(5) The function abs( ) returns

(a) absolute value

(b) negative value

(c) both (a) and (b)

(d) none of the above

(6) The use of parenthesis is optional with one of the following statement

(a) return

(b) main

(c) clrscr

(d) exit

(7) Which of the following program will generate an error message:

 void main( )

 {

 return 0;

 }

  (a) main( ) cannot return value

  (b) void keyword in not allowed to main( )

  (c) function should return a non-zero value

  (d) return statement is not allowed

(8) Which of the following statements are true?

     (1) A return type of void specifies that no value be returned

     (2) Functions by default return int value

     (3) The return type can only be int, char or double

(a) (1) and (2)

(b) (1),(2) and (3)

(c) (1) and (3)

(d) none of the above

(9) C++ provides inline functions to facilitate reduce function call overhead, mainly for

(a) small functions

(b) large functions

(c) member functions

(d) none of the above

(10) To—— an inline function, we must change it to an outline function.

(a) debug

(b) edit

(c) remove

(d) comment out

(11) Identify which of the following function calls are allowed. The prototype declaration is int sum(int j, int k=4, int l=3);

(1)sum(2);

(2)sum(2,3);

(3)sum( )

(4)sum(3,4,5);

(a) 1,2 and 4

(b) 2,3 and 4

(c) 1 and 5

(d) 2 and 4

(12) It is possible to overload function

(a) when they have similar name and return type

(b) when they have similar name, return type and different arguments

(c) when they have similar name, different argument type and different return type

(d) when they have similar name, different types of argument, or different number of arguments and return type does not matter

(13) What will be the output of the following program?

  int sub(int q)

{

      int m;

      m-=sub(q-1);

      return(m);

}

void main( )

{

     int r=sub(7);

     cout<<r;

}

(a) 0

(b) stack overflow

(c) compilation error

(d) – 5

[C] Attempt the following programs.

(1) Write a program to define a function with default argument. Whenever the function needs default values of arguments, it will prompt the user to enter a default value. Display the values.

(2) Write a program to define a constant variable. Change its value using pointer. Display default and the new assigned values with memory locations.

(3) Write a program to calculate the power of a given number. Define user-defined function power( ). Make it inline.

(4) Write a program to accept a double number. Separate its integer and fractional part.

(5) Write a program to calculate absolute value of long and float number.

(6) Write a program to round down and round up the floating point number.

(7) Write a program to overload the function uabs( ). The function should return absolute value of the given number for data type int and float.

(8) Write a program to enter quantity and rate through the keyboard. Calculate the amount by multiplying quantity and rate. If the fractional part of the amount is greater or equal to .50 then round up the number otherwise round down the number. Enter minimum 10 records. Calculate separately the total fractional parts of amount rounded up and down.

(9) Write a program to display only integer portion of the given float numbers without type casting.

(10) Write a program to accept a float number through the keyboard. Calculate the square of the number. Separate the float number into integer and fractional part. Individually calculate the square of an integer and fractional parts and add them in another variable. Compare the two squares obtained. Write your observation regarding the squares obtained. (Note: set precision to 2)

(11) Write a program to calculate the square root of 1 to 10 numbers. Display the sum of integer parts and fractional parts of the square roots obtained. (Note: set precision to 2)

(12) Write a program to overload function to convert an integer number to an ASCII character and float to ASCII string.

(13) Write an inline function to display lines of different patterns.

(14) Write a program to find the power of integer number like pow( ) library function.

(15) Write a program to return more than one values from function. Use call by reference method.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.41.229