4.1 C++ Functions

You might also like

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 98

C++ Functions

Functions and subprograms

• The Top-down design appeoach is based on dividing the


main problem into smaller tasks which may be divided into
simpler tasks, then implementing each simple task by a
subprogram or a function
• A C++ function or a subprogram is simply a chunk of C++
code that has
• A descriptive function name, e.g.
• computeTaxes to compute the taxes for an employee
• isPrime to check whether or not a number is a prime number
• A returning value
• The computeTaxes function may return with a double number
representing the amount of taxes
• The isPrime function may return with a Boolean value (true or false)

2
C++ Standard Functions

• C++ language is shipped with a lot of functions


which are known as standard functions
• These standard functions are groups in different
libraries which can be included in the C++ program,
e.g.
• Math functions are declared in <math.h> library
• Character-manipulation functions are declared in
<ctype.h> library
• C++ is shipped with more than 100 standard libraries,
some of them are very popular such as <iostream.h> and
<stdlib.h>, others are very specific to certain hardware
platform, e.g. <limits.h> and <largeInt.h>

3
User-Defined C++ Functions

• Although C++ is shipped with a lot of standard


functions, these functions are not enough for all
users, therefore, C++ provides its users with a way
to define their own functions (or user-defined
function)
• For example, the <math.h> library does not include
a standard function that allows users to round a real
number to the ith digits, therefore, we must declare
and implement this function ourselves

4
What is The Syntactic Structure of a
C++ Function?
• A C++ function consists of two parts
• The function header, and
• The function body
• The function header has the following syntax
<return value> <name> (<parameter list>)
• The function body is simply a C++ code enclosed between { }

5
Example of User-defined
C++ Function

double computeTax(double income)


{
if (income < 5000.0) return 0.0;
double taxes = 0.07 * (income-5000.0);
return taxes;
}

6
Example of User-defined
C++ Function
Function
header

double computeTax(double income)


{
if (income < 5000.0) return 0.0;
double taxes = 0.07 * (income-5000.0);
return taxes;
}

7
Why Do We Need Function
Signature?
• For Information Hiding
• If you want to create your own library and share it with
your customers without letting them know the
implementation details, you should declare all the
function signatures in a header (.h) file and distribute the
binary code of the implementation file
• For Function Abstraction
• By only sharing the function signatures, we have the
liberty to change the implementation details from time to
time to
• Improve function performance
• make the customers focus on the purpose of the function, not its
implementation

8
Example
double computeTaxes(double income)
#include <iostream>
#include <string>
{
using namespace std; if (income<5000) return 0.0;
return 0.07*(income-5000.0);
// Function Signature }
double getIncome(string);
double computeTaxes(double); double getIncome(string prompt)
void printTaxes(double); {
cout << prompt;
void main() double income;
{
cin >> income;
// Get the income;
return income;
double income = getIncome("Please enter the
employee income: "); }

// Compute Taxes void printTaxes(double taxes)


double taxes = computeTaxes(income); {
cout << "The taxes is $" << taxes << endl;
// Print employee taxes }
printTaxes(taxes);
} 9
Building Your Libraries

• It is a good practice to build libraries to be used by you and your


customers
• In order to build C++ libraries, you should be familiar with
• How to create header files to store function signatures
• How to create implementation files to store function implementations
• How to include the header file to your program to use your user-defined
functions

10
C++ Header Files

• The C++ header files must have .h extension and should have the
following structure
• #ifndef compiler directive
• #define compiler directive
• May include some other header files
• All functions signatures with some comments about their purposes, their
inputs, and outputs
• #endif compiler directive

11
TaxesRules Header file

#ifndef _TAXES_RULES_ double computeTaxes(double);


#define _TAXES_RULES_ // purpose -- to compute the taxes for a
given income
#include <iostream> // input -- a double value representing
the income
#include <string> // output -- a double value representing
using namespace std; the taxes

double getIncome(string); void printTaxes(double);


// purpose -- to get the employee // purpose -- to display taxes to the user
income // input -- a double value representing
// input -- a string prompt to be the taxes
displayed to the user // output -- None
// output -- a double value
representing the income
#endif

12
TaxesRules Implementation File

#include "TaxesRules.h"

double computeTaxes(double income)


{
void printTaxes(double taxes)
if (income<5000) return 0.0;
{
return 0.07*(income-5000.0);
} cout << "The taxes is $" << taxes <<
endl;
}
double getIncome(string prompt)
{
cout << prompt;
double income;
cin >> income;
return income;
}

13
Main Program File

#include "TaxesRules.h"
void main()
{
// Get the income;
double income =
getIncome("Please enter the employee income: ");

// Compute Taxes
double taxes = computeTaxes(income);

// Print employee taxes


printTaxes(taxes);
}
14
Inline Functions

• Sometimes, we use the keyword inline to define


user-defined functions
• Inline functions are very small functions, generally, one or
two lines of code
• Inline functions are very fast functions compared to the
functions declared without the inline keyword
• Example
inline double degrees( double radian)
{
return radian * 180.0 / 3.1415;
}

15
Example #1
• Write a function to test if a number is an odd number

inline bool odd (int x)


{
return (x % 2 == 1);
}

16
Example #2

• Write a function to compute the distance between


two points (x1, y1) and (x2, y2)

Inline double distance (double x1, double y1,


double x2, double y2)
{
return sqrt(pow(x1-x2,2)+pow(y1-y2,2));
}

17
Example #3

• Write a function to compute n!

int factorial( int n)


{
int product=1;
for (int i=1; i<=n; i++) product *= i;
return product;
}

18
Example #4
Function Overloading
• Write functions to return with the maximum number of two
numbers An overloaded
function is a
inline int max( int x, int y) function that is
{ defined more than
if (x>y) return x; else return y; once with different
}
data types or
inline double max( double x, double y) different number
{ of parameters
if (x>y) return x; else return y;
}

19
Sharing Data Among
User-Defined Functions
•There are two ways to share data among
different functions
• Using global variables (very bad practice!)
• Passing data through function parameters
• Value parameters
• Reference parameters
• Constant reference parameters

20
C++ Variables

• A variable is a place in memory that has


• A name or identifier (e.g. income, taxes, etc.)
• A data type (e.g. int, double, char, etc.)
• A size (number of bytes)
• A scope (the part of the program code that can use it)
• Global variables – all functions can see it and using it
• Local variables – only the function that declare local variables see
and use these variables
• A life time (the duration of its existence)
• Global variables can live as long as the program is executed
• Local variables are lived only when the functions that define these
variables are executed

21
I. Using Global Variables

#include <iostream.h>
int x = 0;
void f1() { x++; }
void f2() { x+=4; f1(); }
void main()
{
f2();
cout << x << endl;
}

22
I. Using Global Variables
x 0
#include <iostream.h>
int x = 0;
void f1() { x++; }
void f2() { x+=4; f1(); }
void main()
{
f2();
cout << x << endl;
}

23
I. Using Global Variables
x 0
#include <iostream.h>
int x = 0;
void f1() { x++; }
void f2() { x+=4; f1(); }
void main()
{
f2();
cout << x << endl;
} void main()
{
1 f2();
cout << x << endl ;
}
24
I. Using Global Variables
x 0
4
#include <iostream.h>
int x = 0;
void f1() { x++; }
void f2() { x+=4; f1(); }
void main() void f2()
{ {
2 x += 4;
f2(); f1();
cout << x << endl; }
} void main()
{
1 f2();
cout << x << endl ;
}
25
I. Using Global Variables
x 5
4
#include <iostream.h>
int x = 0; void f1()
{
void f1() { x++; } 4 x++;
void f2() { x+=4; f1(); } }
void main() void f2()
{ {
x += 4;
f2(); 3 f1();
cout << x << endl; }
} void main()
{
1 f2();
cout << x << endl ;
}
26
I. Using Global Variables
x 5
4
#include <iostream.h>
int x = 0; void f1()
{
void f1() { x++; } x++;
void f2() { x+=4; f1(); } 5 }
void main() void f2()
{ {
x += 4;
f2(); 3 f1();
cout << x << endl; }
} void main()
{
1 f2();
cout << x << endl;
}
27
I. Using Global Variables
x 5
4
#include <iostream.h>
int x = 0;
void f1() { x++; }
void f2() { x+=4; f1(); }
void main() void f2()
{ {
x += 4;
f2(); f1();
cout << x << endl; 6 }
} void main()
{
1 f2();
cout << x << endl;
}
28
I. Using Global Variables

#include <iostream.h> x 5
4

int x = 0;
void f1() { x++; }
void f2() { x+=4; f1(); }
void main()
{
f2();
cout << x << endl; void main()
{
} f2();
7 cout << x << endl;
}
29
I. Using Global Variables

#include <iostream.h> x 5
4

int x = 0;
void f1() { x++; }
void f2() { x+=4; f1(); }
void main()
{
f2();
cout << x << endl; void main()
{
} f2();
cout << x << endl;
8 }
30
I. Using Global Variables

#include <iostream.h>
int x = 0;
void f1() { x++; }
void f2() { x+=4; f1(); }
void main()
{
f2();
cout << x << endl;
}

31
What Happens When We Use Inline
Keyword?
#include <iostream.h>
int x = 0;
Inline void f1() { x++; }
Inline void f2() { x+=4; f1();}
void main()
{
f2();
cout << x << endl;
}

32
What Happens When We Use Inline
Keyword?
#include <iostream.h> x 0

int x = 0;
Inline void f1() { x++; } The inline keyword
instructs the compiler
Inline void f2() { x+=4; f1();} to replace the function
call with the function
void main() body!
{
f2(); void main()
cout << x << endl; {
1 x+=4;
} x++;
cout << x << endl;
}
33
What Happens When We Use Inline
Keyword?
#include <iostream.h> x 4

int x = 0;
Inline void f1() { x++; }
Inline void f2() { x+=4; f1();}
void main()
{
f2(); void main()
cout << x << endl; {
x+=4;
} 2 x++;
cout << x << endl;
}
34
What Happens When We Use Inline
Keyword?
#include <iostream.h> x 5

int x = 0;
Inline void f1() { x++; }
Inline void f2() { x+=4; f1();}
void main()
{
f2(); void main()
cout << x << endl; {
x+=4;
} x++;
3 cout << x << endl;
}
35
What Happens When We Use Inline
Keyword?
#include <iostream.h> x 5

int x = 0;
Inline void f1() { x++; }
Inline void f2() { x+=4; f1();}
void main()
{
f2(); void main()
cout << x << endl; {
x+=4;
} x++;
cout << x << endl;
4 }
36
What Happens When We Use Inline
Keyword?
#include <iostream.h>
int x = 0;
Inline void f1() { x++; }
Inline void f2() { x+=4; f1();}
void main()
{
f2();
cout << x << endl;
}

37
What is Bad About Using
Global Vairables?
• Not safe!
• If two or more programmers are working together in a
program, one of them may change the value stored in the
global variable without telling the others who may
depend in their calculation on the old stored value!
• Against The Principle of Information Hiding!
• Exposing the global variables to all functions is against the
principle of information hiding since this gives all
functions the freedom to change the values stored in the
global variables at any time (unsafe!)

38
Local Variables

• Local variables are declared inside the function


body and exist as long as the function is running and
destroyed when the function exit
• You have to initialize the local variable before using
it
• If a function defines a local variable and there was a
global variable with the same name, the function
uses its local variable instead of using the global
variable

39
Example of Defining and Using
Global and Local Variables
#include <iostream.h>
int x; // Global variable
Void fun(); // function signature

void main()
{
x = 4;
fun();
cout << x << endl;
}

void fun()
{
int x = 10; // Local variable
cout << x << endl;
} 40
Example of Defining and Using
Global and Local Variables
#include <iostream.h> x 0
int x; // Global variable
Void fun(); // function signature Global variables are
automatically initialized to 0
void main()
{
x = 4;
fun();
cout << x << endl;
}

void fun()
{
int x = 10; // Local variable
cout << x << endl;
} 41
Example of Defining and Using
Global and Local Variables
#include <iostream.h> x 0
int x; // Global variable
Void fun(); // function signature

void main()
{
x = 4;
fun();
cout << x << endl;
}

void fun() void main()


{ {
1 x = 4;
int x = 10; // Local variable
fun();
cout << x << endl; cout << x << endl;
} } 42
Example of Defining and Using
Global and Local Variables
#include <iostream.h> x 4
int x; // Global variable
Void fun(); // function signature

void main() void fun()


{
x ????
x = 4;
fun(); {
3 int x = 10;
cout << x << endl;
cout << x << endl;
} }

void fun() void main()


{ {
x = 4;
int x = 10; // Local variable
2 fun();
cout << x << endl; cout << x << endl;
} } 43
Example of Defining and Using
Global and Local Variables
#include <iostream.h> x 4
int x; // Global variable
Void fun(); // function signature

void main() void fun()


{
x 10
x = 4;
fun(); {
3 int x = 10;
cout << x << endl;
cout << x << endl;
} }

void fun() void main()


{ {
x = 4;
int x = 10; // Local variable
2 fun();
cout << x << endl; cout << x << endl;
} } 44
Example of Defining and Using Global
and Local Variables
#include <iostream.h>
x 4
int x; // Global variable
Void fun(); // function signature

void main()
void fun()
{
x = 4; x 10
fun();
{
cout << x << endl;
int x = 10;
}
4 cout << x << endl;
}
void fun()
{ void main()
int x = 10; // Local variable {
cout << x << endl; x = 4;
} 2 fun();
cout << x << endl;
} 45
Example of Defining and Using Global
and Local Variables
#include <iostream.h>
x 4
int x; // Global variable
Void fun(); // function signature

void main()
void fun()
{
x = 4; x 10
fun();
{
cout << x << endl;
int x = 10;
}
cout << x << endl;
5 }
void fun()
{ void main()
int x = 10; // Local variable {
cout << x << endl; x = 4;
} 2 fun();
cout << x << endl;
} 46
Example of Defining and Using Global
and Local Variables
#include <iostream.h>
x 4
int x; // Global variable
Void fun(); // function signature

void main()
{
x = 4;
fun();
cout << x << endl;
}

void fun()
{ void main()
int x = 10; // Local variable {
cout << x << endl; x = 4;
} fun();
6 cout << x << endl;
} 47
Example of Defining and Using Global
and Local Variables
#include <iostream.h>
x 4
int x; // Global variable
Void fun(); // function signature

void main()
{
x = 4;
fun();
cout << x << endl;
}

void fun()
{ void main()
int x = 10; // Local variable {
cout << x << endl; x = 4;
} fun();
cout << x << endl;
7 } 48
II. Using Parameters
• Function Parameters come in three flavors:
• Value parameters – which copy the values of the function arguments
• Reference parameters – which refer to the function arguments by other local
names and have the ability to change the values of the referenced arguments
• Constant reference parameters – similar to the reference parameters but cannot
change the values of the referenced arguments

49
Value Parameters
• This is what we use to declare in the function signature or
function header, e.g.
int max (int x, int y);
• Here, parameters x and y are value parameters
• When you call the max function as max(4, 7), the values 4 and 7 are
copied to x and y respectively
• When you call the max function as max (a, b), where a=40 and b=10, the
values 40 and 10 are copied to x and y respectively
• When you call the max function as max( a+b, b/2), the values 50 and 5 are
copies to x and y respectively
• Once the value parameters accepted copies of the
corresponding arguments data, they act as local variables!

50
Example of Using Value Parameters
and Global Variables
#include <iostream.h> x 0
int x; // Global variable
void fun(int x)
{
cout << x << endl;
x=x+5;
}
void main()
{
void main()
x = 4; {
fun(x/2+1); 1 x = 4;
cout << x << endl; fun(x/2+1);
cout << x << endl;
} } 51
Example of Using Value Parameters and
Global Variables
#include <iostream.h> x 4
int x; // Global variable
void fun(int x)
{
cout << x << endl;
x=x+5; void fun(int x )
{
} 3 cout << x << endl;
void main() x=x+5;
{ }
x = 4;
fun(x/2+1); void main()
{
cout << x << endl; x = 4; 3
} 2 fun(x/2+1);
cout << x << endl;
} 52
Example of Using Value Parameters and
Global Variables
#include <iostream.h> x 4
int x; // Global variable
void fun(int x)
{
cout << x << endl;
x=x+5; void fun(int x 8
3 )
{
} cout << x << endl;
void main() 4 x=x+5;
{ }
x = 4;
fun(x/2+1); void main()
{
cout << x << endl; x = 4;
} 2 fun(x/2+1);
cout << x << endl;
} 53
Example of Using Value Parameters and
Global Variables
#include <iostream.h> x 4
int x; // Global variable
void fun(int x)
{
cout << x << endl;
x=x+5; void fun(int x 3
8 )
{
} cout << x << endl;
void main() x=x+5;
{ 5 }
x = 4;
fun(x/2+1); void main()
{
cout << x << endl; x = 4;
} 2 fun(x/2+1);
cout << x << endl;
} 54
Example of Using Value Parameters and
Global Variables
#include <iostream.h> x 4
int x; // Global variable
void fun(int x)
{
cout << x << endl;
x=x+5;
}
void main()
{
x = 4;
fun(x/2+1); void main()
{
cout << x << endl; x = 4;
} fun(x/2+1);
6 cout << x << endl;
} 55
Example of Using Value Parameters and
Global Variables
#include <iostream.h> x 4
int x; // Global variable
void fun(int x)
{
cout << x << endl;
x=x+5;
}
void main()
{
x = 4;
fun(x/2+1); void main()
{
cout << x << endl; x = 4;
} fun(x/2+1);
cout << x << endl;
7 } 56
Reference Parameters

• As we saw in the last example, any changes in the


value parameters don’t affect the original function
arguments
• Sometimes, we want to change the values of the
original function arguments or return with more
than one value from the function, in this case we
use reference parameters
• A reference parameter is just another name to the
original argument variable
• We define a reference parameter by adding the & in front
of the parameter name, e.g.
double update (double & x);

57
Example of Reference Parameters
#include <iostream.h>
void fun(int &y)
{
cout << y << endl;
y=y+5;
}
void main()
{
int x = 4; // Local variable void main()
{
fun(x); ?
4 x
1 int x = 4;
cout << x << endl; fun(x);
} cout << x << endl;
}
58
Example of Reference Parameters
#include <iostream.h>
void fun(int &y)
{
cout << y << endl;
void fun( int & y )
y=y+5; {
} 3 cout<<y<<endl;
void main() y=y+5;
}
{
int x = 4; // Local variable void main()
fun(x); {
int x = 4; ?
4 x
cout << x << endl; 2 fun(x);
} cout << x << endl;
}
59
Example of Reference Parameters
#include <iostream.h>
void fun(int &y)
{
cout << y << endl;
void fun( int & y )
y=y+5; {
} cout<<y<<endl;
void main() 4 y=y+5;
9
}
{
int x = 4; // Local variable void main()
fun(x); {
int x = 4; ?
4 x
cout << x << endl; 2 fun(x);
} cout << x << endl;
}
60
Example of Reference Parameters
#include <iostream.h>
void fun(int &y)
{
cout << y << endl;
void fun( int & y )
y=y+5; {
} cout<<y<<endl;
void main() y=y+5;
5 }
{
int x = 4; // Local variable void main()
fun(x); {
int x = 4; ?
9 x
cout << x << endl; 2 fun(x);
} cout << x << endl;
}
61
Example of Reference Parameters
#include <iostream.h>
void fun(int &y)
{
cout << y << endl;
y=y+5;
}
void main()
{
int x = 4; // Local variable void main()
fun(x); {
int x = 4; ?
9 x
cout << x << endl; fun(x);
} 6 cout << x << endl;
}
62
Example of Reference Parameters
#include <iostream.h>
void fun(int &y)
{
cout << y << endl;
y=y+5;
}
void main()
{
int x = 4; // Local variable void main()
fun(x); {
int x = 4; ?
9 x
cout << x << endl; fun(x);
} cout << x << endl;
7 }
63
Constant Reference Parameters
• Constant reference parameters are used under the
following two conditions:
• The passed data are so big and you want to save time and
computer memory
• The passed data will not be changed or updated in the
function body
• For example
void report (const string & prompt);
• The only valid arguments accepted by reference
parameters and constant reference parameters are
variable names
• It is a syntax error to pass constant values or expressions to
the (const) reference parameters
64
what is macro?

• A macro is a fragment of code which has been given a name. Whenever


the name is used, it is replaced by the contents of the macro.

• We can define macro using #define.

65
Inline Function
•DEFINITION:
In C++,the functions that are not actually called, rather
their code is expanded in line at the point of each invocation such
functions are called as inline functions.

66
SYNTAX
prototype fun_name( ); //function declaration
main( )
{
--------------------------
fun_name( ); //function call
}
inline prototype fun_name( );
//function definition
{
-------
}

67
WHY THERE IS A NEED OF INLINE
FUNCTIONS?

• A significant amount of overhead is generated by calling and return


mechanism of function.

• While calling the function arguments are pushed onto the stack and
saved on various registers and restore when function returns , this will
take more time to run.

• If we expand a function code inline then function call produce faster run
times.

68
Function Vs Inline Function

• In many places we create the functions for small work/functionality


which contain simple and less number of executable instruction.

• Imagine their calling overhead each time they are being called by callers.

69
• When a normal function call instruction is encountered,
the program stores the memory address of the
instructions immediately following the function call
statement, loads the function being called into the
memory, copies argument values, jumps to the memory
location of the called function, executes the function
codes, stores the return value of the function, and then
jumps back to the address of the instruction that was
saved just before executing the called function.
• Too much run time overhead.

70
• The C++ inline function provides an alternative. With
inline keyword, the compiler replaces the function call
statement with the function code itself (process called
expansion) and then compiles the entire code.
• Thus, with inline functions, the compiler does not have to
jump to another location to execute the function, and
then jump back as the code of the called function is
already available to the calling program.

71
SOME OF THE SITUATION WHERE
INLINE EXPANSION MAY NOT WORK
• If the function code is large.

• If the function is recursive function .

• If the function contains static variables.

• For function returning values, if a loop, a switch , or a goto exists

72
73
74
75
More C++ Concepts

• Operator overloading
• Friend Function
• This Operator
• Inline Function

76
Operator overloading

• Programmer can use some operator symbols to define special


member functions of a class

• Provides convenient notations for object behaviors

77
Why Operator Overloading

int i, j, k; // integers
float m, n, p; // floats The compiler overloads
the + operator for built-in
integer and float types by
k = i + j; default, producing integer
// integer addition and assignment addition with i+j, and
p = m + n; floating addition with m+n.
// floating addition and assignment

We can make object operation look like individual


int variable operation, using operator functions
Complex a,b,c;
c = a + b;
78
Operator Overloading Syntax

• Syntax is: Examples:


operator+
operator-
operator@(argument-list)
operator*
operator/
--- operator is a function
--- @ is one of C++ operator symbols (+, -, =, etc..)

79
Example of Operator Overloading
class CStr
{ void CStr::cat(char *s)
char *pData; {
int nLength; int n;
public: char *pTemp;
// … n=strlen(s);
void cat(char *s); if (n==0) return;
// …
CStr operator+(CStr str1, CStr str2); pTemp=new char[n+nLength+1];
CStr operator+(CStr str, char *s); if (pData)
CStr operator+(char *s, CStr str); strcpy(pTemp,pData);

//accessors strcat(pTemp,s);
char* get_Data();
pData=pTemp;
nLength+=n;
int get_Len();
}
}; 80
The Addition (+) Operator
CStr CStr::operator+(CStr str1, CStr str2)
{
CStr new_string(str1);
//call the copy constructor to initialize an
//entirely new CStr object with the first //operand
new_string.cat(str2.get_Data());
//concatenate the second operand onto the
//end of new_string
return new_string;
//call copy constructor to create a copy of
//the return value new_string
}

new_string

str1
strcat(str1,str2)
strlen(str1)
strlen(str1)+strlen(str2)
81
How does it work?
CStr first(“John”);
CStr last(“Johnson”);
CStr name(first+last);

CStr CStr::operator+(CStr str1,CStr str2)


{
CStr new_string(str1);
new_string.cat(str2.get());
return new_string;
}

name “John Johnson”


Copy constructor
Temporary CStr object

82
Implementing Operator Overloading
• Two ways:
• Implemented as member functions
• Implemented as non-member or Friend functions
• the operator function may need to be declared as a friend if it requires access to protected or
private data

• Expression obj1@obj2 translates into a function call


• obj1.operator@(obj2), if this function is defined within class
obj1
• operator@(obj1,obj2), if this function is defined outside the
class obj1

83
Implementing Operator Overloading

1. Defined as a member function


class Complex {
...
public:
... c = a+b;
Complex operator +(const Complex &op)
{
double real = _real + op._real,
c = a.operator+ (b);
imag = _imag + op._imag;
return(Complex(real, imag));
}
...
};
84
Implementing Operator Overloading

2. Defined as a non-member function


class Complex {
... c = a+b;
public:
...
double real() { return _real; } c = operator+ (a, b);
//need access functions
double imag() { return _imag; }
...
}; Complex operator +(Complex &op1, Complex &op2)
{
double real = op1.real() + op2.real(),
imag = op1.imag() + op2.imag();
return(Complex(real, imag));
} 85
Implementing Operator Overloading

3. Defined as a friend function


class Complex {
... c = a+b;
public:
...
friend Complex operator +( c = operator+ (a, b);
const Complex &,
const Complex &
);
... Complex operator +(Complex &op1, Complex &op2)
}; {
double real = op1._real + op2._real,
imag = op1._imag + op2._imag;
return(Complex(real, imag));
} 86
Ordinary Member Functions, Static Functions
and Friend Functions

1. The function can access the private part of the class definition
2. The function is in the scope of the class
3. The function must be invoked on an object

Which of these are true about the different functions?

87
What is ‘Friend’?
• Friend declarations introduce extra coupling between classes
• Once an object is declared as a friend, it has access to all non-public members as if
they were public
• Access is unidirectional
• If B is designated as friend of A, B can access A’s non-public members; A cannot
access B’s

• A friend function of a class is defined outside of that class's scope

88
More about ‘Friend’
• The major use of friends is
• to provide more efficient access to data members than
the function call
• to accommodate operator functions with easy access to
private data members
• Friends can have access to everything, which
defeats data hiding, so use them carefully
• Friends have permission to change the internal state
from outside the class. Always recommend use
member functions instead of friends to change state

89
Assignment Operator
• Assignment between objects of the same type is always
supported
• the compiler supplies a hidden assignment function if you don’t write your
own one
• same problem as with the copy constructor - the member by member
copying

• Syntax:

class& class::operator=(const class &arg)


{
//…
}

90
Example: Assignment for CStr class
Assignment operator for CStr:
CStr& CStr::operator=(const CStr & source)

Return type - a reference to Argument type - a reference to a CStr object


(address of) a CStr object (since it is const, the function cannot modify it)

CStr& CStr::operator=(const CStr &source){


//... Do the copying
return *this; Assignment function is called as a
} member function of the left operand
=>Return the object itself
str1=str2;
Copy Assignment is different from
Copy Constructor
str1.operator=(str2)
91
The “this” pointer
• Within a member function, the this keyword is a pointer to the current
object, i.e. the object through which the function was called
• C++ passes a hidden this pointer whenever a member function is called
• Within a member function definition, there is an implicit use of this pointer
for references to data members

this Data member reference Equivalent to


pData pData this->pData
nLength this->nLength
nLength

CStr object
(*this)
92
Overloading stream-insertion and
stream-extraction operators
• In fact, cout<< or cin>> are operator overloading built in C++ standard
lib of iostream.h, using operator "<<" and ">>"
• cout and cin are the objects of ostream and istream classes,
respectively
• We can add a friend function which overloads the operator <<
friend ostream& operator<< (ostream &os, const Date &d);

ostream& operator<<(ostream &os, const Date &d)


{
os<<d.month<<“/”<<d.day<<“/”<<d.year;
return os;
cout ---- object of ostream
}

cout<< d1; //overloaded operator
93
Overloading stream-insertion and
stream-extraction operators
• We can also add a friend function which overloads the
operator >>
friend istream& operator>> (istream &in, Date &d);

istream& operator>> (istream &in, Date &d)


{
char mmddyy[9];
in >> mmddyy; cin ---- object of istream
// check if valid data entered
if (d.set(mmddyy)) return in;
cout<< "Invalid date format: "<<d<<endl;
exit(-1);
}
cin >> d1;

94
Inline functions
• An inline function is one in which the function
code replaces the function call directly.
• Inline class member functions
• if they are defined as part of the class definition,
implicit
• if they are defined outside of the class definition,
explicit, I.e.using the keyword, inline.
• Inline functions should be short (preferable
one-liners).
• Why? Because the use of inline function results in
duplication of the code of the function for each
invocation of the inline function  

95
Example of Inline functions
class CStr
{
char *pData;
int nLength;

public: Inline functions within class declarations

char *get_Data(void) {return pData; }//implicit inline function
int getlength(void);

};
inline void CStr::getlength(void) //explicit inline function
{
return nLength;
} Inline functions outside of class declarations

 
int main(void)
{
char *s;
int n;
CStr a(“Joe”);
s = a.get_Data();
In both cases, the compiler will insert the
n = b.getlength(); code of the functions get_Data() and
}
getlength() instead of generating calls to these
functions 96
Inline functions (II)

• An inline function can never be located in a run-time library since the


actual code is inserted by the compiler and must therefore be known at
compile-time.
• It is only useful to implement an inline function when the time which is
spent during a function call is long compared to the code in the function.

97
Take Home Message

• Operator overloading provides convenient notations for object behaviors

• There are three ways to implement operator overloading


• member functions
• normal non-member functions
• friend functions

98

You might also like