Overloading and Inline Function in C++
Overloading and Inline Function in C++
TABLE OF CONTENTS
TITLE PAGE NO.
List of Tables .... 1 List of Figures..1 Introduction ..... 2 1- Overloading operators .....3 1-1 Defining operator overloading.....4 1-2 Overloading unary operators ......7 1-3 Overloading binary operators......10 2- Overloading function ......12 3- Inline function .....16 3-1 What is inline function..........16 3-2 Advantage and disadvantage .......16 3-3 General format of inline function .........16 3-4 inline function implementation .......17 References ..18
List of Tables
[Table (1): C++ places in the programming languages]... 2 [Table (2): Unary operators] ... 5 [Table (3): Binary operators] .. 5
List of Figures
[Figure (1): Structure of C++ program]... 2 [ Figure (2): The general syntax of an operator function] ...4 [Figure (3): The general format of inline function]... 16
Introduction:
C++ is an object oriented language . Initially named C with classes . This language was developed by Bjarne Stroustrup at Bell labs in Murray Hill, New jersy , USA in the early eighties. C++ is often called a middlelevel computer language, which it means that is combines elements of highlevel languages with the functionalism of assembly language. The table (1) below show C++ fits into spectrum of languages. Level Highest-level Middle-level Lowest-level languages PASCAL , BASIC , FORTRAN C++ , C , Macro-assembly Assembly language
Table (1): C++ places in the programming languages
C++ is a Superset of C , Therefore almost all C programs are also C++ programs. In other words: When Bjarne Stroustrup designed C++, he added OOP (Object Oriented Programming) features to C without significantly changing the C component. Thus C++ is a "relative" of C, meaning that any valid C program is also a valid C++ program. The program in C++ language would contain four sections as show in the following figure (1).
Include files Class declaration Class functions definitions Main function program
The One of the important features of OPP, it is Polymorphism. It simple means one name, multiple forms. Polymorphism can be applied in the C++ language in two cases: either during run-time (dynamic binding) or during compile-time (static binding).The latter case is applied in two methods: The
2
first method is called overloading operators using some operators in C++. And the second method is called overloading functions using functions. Therefore I will cover these methods with some examples that show this property useful and difficult at the same time.
1 - Overloading operators:
C++ has a number of built-in types, including int, real, char, and so forth. Each of these has a number of built-in operators, such as addition (+) and multiplication (*).The operators are symbols. C++ has more than 40 operators. C++ enables you to add these operators to your own classes as well. Almost all C++ operators can be overloaded. Operator overloading is the ability to tell the compiler how to perform a certain operation when its corresponding operator is used on one or more variables. For example, the compiler acts differently with regards to the subtraction operator - depending on how the operator is being used. When it is placed on the left of a numeric value such as -48, the compiler considers the number a negative value. When used between two integral values, such as 80-712, the compiler applies the subtraction operation. When used between an integer and a double-precision number, such as 558-9.27, the compiler subtracts the left number from the right number; the operation produces a double-precision number. When the - symbol is doubled and placed on one side of a variable, such as --Variable or Variable--, the value of the variable needs to be decremented; in other words, the value 1 shall be subtracted from it. All of these operations work because the subtraction operator - has been reconfigured in various classes to act suitably. The Overloading an operator means having two or more definitions for an operator. C++ treats operators as special kinds of functions. Operator overloading is a very important feature of Object Oriented Programming. Curious to know why!!? It is because by using this facility programmer would be able to create new definitions to existing operators. In fact in other words a single operator can take up several functions as desired by programmers depending on the argument taken by the operator by using the operator overloading facility. After knowing about the feature of operator overloading now let me see how to define and use this concept of operator overloading in C++ programming language.
3
Where: <return_type> : is the type of the value returned by the specified operation; operator : is the keyword; <operator_symbol> : is the operator being loaded,[you can see it in table2,3]; arguments_list : represent the list of arguments (parameters) . Operator function must be either member function or a friend function. The basic difference between these functions is that a friend function will have only one argument for unary operators and two for binary operators. While a member function has no arguments for unary operators and only one for binary operators. This is because the object used to invoke the member function is passed implicitly and therefore is available for the member function.
Broadly classifying operators are of two types namely: Unary Operators Binary Operators The unary operators are shown in the following table (2):
Operator ! & ~ * + ++ -conversion operators Logical NOT Address-of One's complement Pointer dereference Unary plus Increment Unary negation Decrement conversion operators Name
= > >* / /= < << <<= <= = == > >= >> >>= ^ ^= | |= ||
Subtraction/assignment Member selection Pointer-to-member selection Division Division/assignment Less than Left shift Left shift/assignment Less than or equal to Assignment Equality Greater than Greater than or equal to Right shift Right shift/assignment Exclusive OR Exclusive OR/assignment Bitwise inclusive OR Bitwise inclusive OR/assignment Logical OR
Notes: 1- The = , ( ), [ ] and -> operators must be defined as member functions. 2- The next five operators cannot be overloaded: :: ( scope resolution operator ) . ( member selection ) .* ( member selection through pointer to function ) sizeof ( size of operator ) ?: ( conditional operator ) 3- You cannot combine operators that currently have no meaning in C++ (such as ** to represent exponentiation).
6
4- You cannot change the number of arguments an operator. 5- You cannot use a symbol that isnt operator, like @ or $. 6- To avoid the copying of large objects when passing them to an overloaded operator, references should be used. Pointers are not suitable for this purpose because an overloaded operator cannot operate exclusively on pointers.
//***********Member Function Definitions************* void minus :: getdata ( int a , int b , int c ) { x=a; y=b; z=c; } void minus :: display ( void ) { cout << "\t x = " << x << endl ; cout << "\t y = " << y << endl ; cout << "\t z = " << z << endl ; } //*********Definition of the operator function *********** void minus :: operator - ( ) { x = -x ; y = -y ; z = -z ; } //*************Main Function Definition**************** main( ) { minus M ; M.getdata ( 10 , -20,30 ) ; cout << " \n M : Before activating the operator - ( ) \n"; M.display( ) ; -M; // operator invoked ( call of operator function ) cout << "\n M : After activating the operator - ( )\n" ; M.display( ) ; }
The output:
M : Before activating the operator - ( ) x = 10 y = -20 z = 30 M : After activating the operator - ( ) x = -10 y = 20 z = -30 In the program above, the declarative of the operator function is given as: void operator ( ) ;
This declarative tells the compiler to call this member function , whenever the operator is encountered, provided the operand is of type minus. The function operator ( ) takes no argument. This function is a member function, and the member functions can directly access the members of an object for which they have been called. Therefore, the operator function for overloading the unary minus operator ( - ) does not require any argument. In other words: Whenever an unary operator is used, it works with one operand, therefore with the user defined data types, the operand becomes the caller and hence no arguments are required In the main( ) function of this program, the object M of type minus is declared and initialized to ( 10, -20, 30 ) as: minus M( 10, -20, 30 ) ; Before activating the operator function, the values of a, b and c are displayed as: x = 10 y = -20 z = 30 After the statement -M; The object M invokes the operator member function unary minus. the function will change the sign of all the data members of the object M. the operator member function gets activated and the values of x, y and z are displayed as: x = -10 y = 20 z = -30 A statement such as M1 = - M2 will yield a compiler error since the unary minus member function is not designed to return any value; however, with a little modification this function will be able to return values. It is possible to overload an unary minus operator in above program using a friend function. This can be done ,just change the declaration and definition of the operator function as follows: friend void operator ( minus & M ); // Declaration as friend function And for definition : void operator ( minus & M) { M.x = - M.x ; M.y = - M.y ; M.z = - M.z ; } The argument must pass by reference because any change to the values it accepted, in other words: Note: In the above definition, we have received the operand by reference because we need to change the values of its data members, which would not be possible if we would receive the argument by value.
9
10
} }; complex a , b , c; c=a+b; This cod will cause a compilation error, since I have not defined the behavior my class should have with addition operations. To perform operations like addition and so on, is necessary to define functions such the below program . // End of the Class Definition
The Program :
//***This program illustrates the overloading of binary operator(+) as member function*** # include <iostream.h> class complex { float re, im; // re = real part, im = imaginary part public: complex ( float real=0 , float imag =0 ) { re = real ; im = imag } void display ( void ) ; complex operator + ( complex op) ; }; // Declaration of the display function // Declaration of the operator function as member function // End of the Class Definition // constructor
//***********Member Function Definitions************* void complex :: display (void) { cout << re << + j << im <<\n; } //*********Definition of the operator function *********** complex complex :: operator + (complex op ) { complex temp ; temp.re = re + op.x ; temp.im = im + op.im ; return (temp) } //*************Main Function Definition**************** main( ) {
11
complex c1,c2,c3 ; c1= complex (2.5 , 3.5) ; c2 = complex ( 1.6 , 2.7); c3 = c1 + c2 ; cout << " \n c1= ; c1.display ( ); cout << c2 = ; c2.display ( ) ; cout << c3 = ; c3.dispaly ( ) }
The output :
c1 = 2.5 +j 3.5 c2 = 1.6 +j 2.7 c3 = 4.1 +j 6.2 Note : only one object can access directly , in the program above: c3 = c1 + c2 is equivalent to : c3 = c1.opertaor + ( c2) It is possible to overload binary addition operator in above program using a friend function. This can be done ,just change the declaration and definition of the operator function as follows: friend complex operator + ( complex , complex ); // Declaration as friend function And for definition: complex operator + ( complex a , complex b) { complex temp ; temp.re = a.re + b.re ; temp.im = a.im + b.im ; return ( temp) }
2 - Overloading function:
C++ enables you to create more than one function with the same name. This is called function overloading. The functions must differ in their parameter list, with a different type of parameter, a different number of parameters, or both. Here's an example (1): int myFunction (int, int) ;
12
int myFunction (long, long) ; int myFunction (long) ; myFunction( ) is overloaded with three different parameter lists. The first and second versions differ in the types of the parameters, and the third differs in the number of parameters. The return types can be the same or different on overloaded functions, as long as the parameter list is different. You can't overload just on return type, however.
Function polymorphism refers to the capability to overload a function with more than one meaning. By changing the number or type of the parameters, you can give two or more functions the same function name, and the right one will be called by matching the parameters used. Suppose you write a function that doubles whatever input you give it. You would like to be able to pass in an int, a long, a float, or a double. Without function overloading, you would have to create four function names: int DoubleInt(int) ; long DoubleLong(long) ; float DoubleFloat(float) ; double DoubleDouble(double) ; With function overloading, you make this declaration: int Double(int) ; long Double(long) ; float Double(float) ; double Double(double) ; This is easier to read and easier to use. You don't have to worry about which one to call; you just pass in a variable, and the right function is called automatically. Finally, a function is overloaded when same name is given to different function. However, the two functions with the same name will differ at least in one of the following. a) The number of parameters. b) The data type of parameters.
13
The program:
//*******************This program illustrates the function overloading************ # include <iostream.h> int volume ( int ) ; double volume (double , int ); long volume (long , int , int ) ; int main ( ) { Cout << \n The volume = << volume (10) << \n ; Cout << The volume = << volume ( 2.5,8 ) << \n ; Cout << The volume = << volume (100,75,15) ; } //************* Function Definitions **************** // The volume of the cube is L3 = L L L int volume ( int d ) { return ( d * d * d ) ; } // The volume of the cylinder is length pi (radius)2 double volume (double r , int L) { return (3.14 * r * r * L) ; } // The volume of the rectangle is length x height x width long volume (long L , int h , int w ) { return ( L * h * w ) ; } // prototype (1) // prototype (2) // prototype (3)
The output :
The volume = 1000 The volume = 157 The volume = 112500
14
Here's an example (3): // declarations : int add ( int a , int b ) ; int add ( int a , int b , int c ) ; double add ( double x , double y ) ; double add ( int p , double q ) ; // function calls cout << add (5 , 10) ; cout << add (5 , 10.0) ; cout << add (12.5 , 7.5) ; cout << add (5 , 10 , 15) ; // use prototype 1 // use prototype 4 // use prototype 3 // use prototype 2 // prototype (1) // prototype (2) // prototype (3) // prototype (4)
Selection function is as the following steps: 1 - First, the compiler tries to find a function exactly (exact match) the same types used in the actual parameters. 2- If the compiler did not find exact match, it will change actual parameters automatically such as ( chat to int ) or ( float to double ). 3-When a failure in the previous two steps, the compiler attempts to use the built-in conversions. The complier will send error at the time. If the result of process of conversion has a several matches. Here's an example (4): long square ( long n ) ; // declaration
Note : will be an error occurs since the compiler maybe will convert the integer to long or double.
15
3 Inline functions:
3-1 What is Inline Function? Inline functions are functions where the call is made to inline functions. The actual code then gets placed in the calling program. 3-2 Advantage and disadvantage: In order to optimize the program for better speed , we can use inline function to chive this goal, this function duplicate the function into main program in order to get vide of the translation of the compiler from main function to sub function the function advantage is when the sub function is small (one or two statements ).In other word , What's the rule of thumb? If you have a small function, one or two statements, it is a candidate for inline. When in doubt, leave it out. Note that inline functions can bring a heavy cost. For example, If the function is called 10 times, the inline code is copied into the calling functions each of those 10 times. The tiny improvement in speed you might achieve is more than swamped by the increase in size of the executable program. Even the speed increase might be illusory. 3-3 General Format of inline Function: If a function is declared with the keyword inline, the compiler does not create a real function: It copies the code from the inline function directly into the calling function. No jump is made; it is just as if you had written the statements of the function right into the calling function.The general format of inline function is as follows: inline function_header { function_body; }
16
3- 4 Inline Function implementation: We can make class method inline. The keyword inline appears before the return value. For example,
inline int cat :: getweight( ) { return itswight ; } // inline // return the weight data member of class cat
We can also put the definition of a function into the declaration of the class, which automatically makes that function inline. For example,
Class cat { Public : int getweight () { return itsweight ; } void setweight( ) ( int weight ) ; }; // end of class // Automatically makes function inline
17
References :
[1] J. Liberty, Teach Yourself C++ in 24 Hours, first Edition, Sams ,USA ,pp. 8592:220-236 , 1997. [2] H. Sutter and Paul J. Deite, C++ How to Program , seventh Edition, person eduction Ltd.,USA ,pp. 467-509, 2009. [3] Safari books online , , http://my.safaribooksonline.com/programming.
[4] S. Oualline , Practical programming C++ , second Edition, OReily ,USA ,pp. 310-345, 2009.
18