Function In C++(A real New Defined Defination)

Document Sample
Function In C++(A real New Defined Defination) Powered By Docstoc
					Functions
I. Basics
Most computer programs used to solve real-world problems are much larger than the
programs we have been writing in class. Experience has proven that the best way to
develop and maintain a large program is to construct it from smaller pieces or
components. Each component is more manageable than the original program and can be
developed and tested independently. Functions are one of the constructs used in C++ to
develop modular programs.

Parameters

Each data item that is sent to a function is called a parameter. A function that computes
the area of a rectangle requires two parameters, length and width.

Return statement

The return statement allows a program to send a single value from the function back to
the program that used the function. The function that computes the area of a rectangle
would return a value for the area. The return statement is also a flow control statement
that returns flow control back to the program that used the function.

Function prototypes

Functions are similar to variables in that both must be declared before they can be used.
There are two ways to handle this. One method is to place all of the function definitions
before the main( ) function. The second and most widely used method is to place a
function prototype before the main( ) function and place the function definition after the
main( ) function or even in a separate file. Function prototypes tell the compiler the name
of the function, the data type returned by the function and a list of the parameter types the
function expects to receive. The function prototype is essentially a method of declaring a
function before it is defined.

 return_data_type function_name (list of parameter types);


Function definitions

The function definition contains the code needed to perform a specific task. The
definition for a function that computes the area of a rectangle would contain a line of
code such as area = length*width;. The header of the function definition is similar in
structure to a function prototype, except it must provide the parameters and not just their
data types.

    return_data_type function_name (parameter list)
    {
        C++ statements
        return (value)
    }

Function calls

A function call refers to actually using the function. The function is called by using its
name and supplying it with appropriate parameters. A function call is a flow control
statement in that the flow of control is passed to the function. Control flow remains with
the function until the return statement is reached and flow control is passed back to the
program using the function..

Example: Here is a function that can compute the area of a rectangle.
# include<iostream>
using namespace std;

double areaRectangle(double, double); // FUNCTION PROTOTYPE

void main( )
{
     double length;
     double width;

       //    Compute the area of a specific rectangle

       cout << "The area of the specific rectangle is = "
            << areaRectangle (12, 4)                    // FUNCTION CALL
             << endl;

       //    Compute the area of any rectangle

       cout << "Next, we compute the area of any rectangle." << endl;
       cout << "Enter the length." << endl;
       cin >> length;
       cout << "Enter the width." << endl;
       cin >> width;
       cout << "The area of the rectangle you chose is = "
            << areaRectangle (length, width)    // FUNCTION CALL
             << endl;
}

double areaRectangle(double l, double w)                  // FUNCTION DEFINITION
{
    return (l*w);
}
II. Passing by value
C++ normally passes by value. When passing by value, the function receives a copy of
the variable. This local copy exists only within the function. Any changes made to the
variable in the functions are not passed back to the program that called the function.
Consider the function

double square (double x)
{
        return x*x;
}

The function call square(a) copies the value of a into x before jumping into the
square( ) function. The advantages of passing by value are simplicity and that the
value of the variable in the calling routine is unchanged after returning from the function.
The two primary disadvantages are that it is inefficient to make a copy of a variable,
especially if it large such an array, structure or a class. Second, the variable in the calling
routine cannot be modified if you want to change it. When passing by value, the only
way to pass information from the function to the calling routine is via the return value of
the function. Only one value may be passed back this way.

Example: Passing by value
# include<iostream>
using namespace std;

void IncreaseMe(int theInt);
main()
{
    int i;
    i = 5;

         cout << "Before function call i = " << i << endl;
     IncreaseMe(i);
         cout << "Before function call i = " << i << endl;

          return 0;
}

void IncreaseMe(int i)
{
     i = i + 1;
         cout << "Inside function i = " << i << endl;
}


III. Passing by reference
A reference is an alias (synonym) for another variable. It is declared using the reference
operator &, which returns the address of the variable to which it is applied. In the
example below r is declared to be a reference for n. In other words, n and r are both
names for the same memory location. Changing the value of one changes the value of the
other.

Example: References are aliases
#include<iostream>
using namespace std;

int main( )
{
        int n = 33;
        int &r = n;

         cout << "r = " << r << " n = " << n << endl;
         n = 50;
         cout << "r = " << r << " n = " << n << endl;
         r++;
         cout << "r = " << r << " n = " << n << endl;

         return 0;
}

When variables are passed into a function by reference, the variable in the calling routine
and the parameter in the function become aliases of one another. No local copies are
made and changes to a variable made by the function will be seen in the calling routine.
There are two advantages of passing by reference. First, passing by reference is more
efficient tan passing by value since no local copies are made. Second, passing by
reference allows us to pass multiple values from the function back to the calling routine
via the parameter list. The disadvantage of passing by reference, is that you may
accidentally change the value of a variable within a function.

Example: Passing by reference
# include<iostream>
using namespace std;

void swap(int &, int &);

void main( )
{
     float first = 20, second = 45;

     cout << "first number =        " << first
                 << " second        number = " << second << endl;
     swap(first, second);
     cout << "first number =        " << first
                 << " second        number = " << second << endl;
}

void swap(int &num1, int &num2)
{
     int temp;

     temp = num1;
     num1 = num2;
     num2 = temp;
     return;
}


IV. Advanced functions
Inline functions

Inline functions are expanded into the program at each function call by the compiler. The
advantage of inline functions is enhanced execution time. The disadvantage is an
increase in the size of the executable file. Inline functions must however be defined prior
to the function call unlike ordinary functions which may be defined after the main
program

# include<iostream>
using namespace std;

inline double FahrenheitToCelcius (double temp)
{
    return (5.0/9.0*(temp - 32.0));
}

int main( )
{
    double fahrenheit;
    cout << "Enter the Fahrenheit temperature: ";
    cin >> fahrenheit;
    cout << "The Celsius temperature is = " <<
FahrenheitToCelcius(fahrenheit) << endl;

     return 0;
}

Default values

Default values are values to be used if no values are provided. The function prototype
void func(int, int =5, float = 6.7); provides default values for the last two parameters. If
values for the parameters are omitted in a function call, the C++ compiler supplies the
default values. Some examples of valid function calls include

func(7, 2, 4.3)
func(7, 2)        is equivalent to func(7, 2, 6.7)
func(7)           is equivalent to func(7, 5, 6.7)

The basic rules for default arguments are
   1. Default values are assigned in function prototypes.
   2. If a parameter has a default value then all subsequent parameters
       must have a default value.
   3. If one argument is omitted in a function call, then all subsequent arguments
       must be omitted.
   4. Default values may be expressions composed of constants and previously defined
      variables.

Function overloading

Many programming languages such as C do not allow you to define more than one
function with the same name. In C++ you can define more than one function with the
same name. This is known as function overloading. The functions could perform widely
different procedures but good programming practice dictates that the procedures should
be similar. There are some rules to ensure the compiler will know which function to use
when the function name is used. The functions must be distinguishable based on their
signatures (the number and data types of their parameters). Overloaded functions cannot
be distinguished only by their return types.

Example: Print the date in two different formats
# include<iostream>
# include<string>
using namespace std;

void printDate (int month, int day, int year);
void printDate (string month, int day, int year);

int main( )
{
    printDate (6,3,1995);
    printDate ("June",3,1995);
    return 0;
}

void printDate (int month, int day, int year)
{
     cout << "The date is: " << month
          << "/" << day << "/" << year << endl;
}

void printDate (string month, int day, int year)
{
     cout << "The date is: " << month
          << " " << day << ", " << year << endl;
}

Function templates

The function template serves as a model for a family of functions which perform
essentially the same procedure but on different data types. The line template <class T>
is called a template prefix and it is used to inform the compiler that the function
immediately following is a template that uses a data type named T. When a function is
called the data type of the argument is substituted for T throughout the function. The
template prefix template<class T1, class T2, class T3> can be used to create a function
template that requires three different data types. The primary reason for studying
templates is that the C++ standard libraries make extensive use of them. The STL or
Standard Template Library is a rich resource for anyone serious about C++ programming.

Example: Square function
# include<iostream>
using namespace std;

template<class Type>        // FUNCTION PROTOTYPE
Type square(Type x);

void main( )
{
     int n1 = 4;
     float n2 = 4.23f;
     double n3 = 4.23456;

     cout << "Square an integer " << square(n1) << endl;
     cout << "Square a float    " << square(n2) << endl;
     cout << "Square a double   " << square(n3) << endl;
}

                            // FUNCTION DEFINITION
template<class Type>        // template prefix
Type square (Type x)
{
     return x*x;
}

Recursion

Recursion is a technique for breaking a large problem into smaller versions of itself. A
recursive algorithm has two parts. First, we need a base case to serve as a means of
stopping the recursion process. Second, we need a recursive step to express the larger
problems in terms of one or more similar but smaller problems. A simple example of this
is the factorial function. The factorial function is traditionally defined as

                              n! n  (n  1)  (n  2)    3  2  1

The same definition can be defined recursively by giving a base case and a recursive step
as
                             Base case        0! 1
                             Recursive step n! n  (n  1)!

A recursive function is a function that calls itself somewhere in the function body. C++
and most modern programming allow recursion. In a recursive function the computation
must “drive” to the base case to ensure the recursion will stop. There are advantages and
disadvantages to recursion and which one wins is problem dependent. The primary
advantage of recursion is that it greatly simplifies some problems. The primary
disadvantage of recursion is the inefficiency of generating a large number of function
calls. Problems that are very difficult to solve without recursion (Towers of Hanoi) are
best solved using recursion and problems that are relatively easy to solve iteratively
(Factorial) should be solved using iteration.

Example: Recursive factorial function
# include<iostream>
using namespace std;

long int factorial (long int);

int main( )
{
    cout << factorial(5) << endl;
    return 0;
}

long int factorial (long int n)
{
     if (n == 0)
                return 1;
     else
                return n*factorial(n-1);
}

Functions as arguments

Functions is C++ can be though of as the addresses of the compiled code in the computers
memory. Hence functions can be passed as parameters to other functions. The following
example shows how one might compute a table of values for a function.

Example: Table of function values.
# include<iostream>
# include<iomanip>
using namespace std;

double f (double);
void table ( double f(double), double, double, int);

int main( )
{
    table(f, 0, 0.5, 100);
    return 0;
}

double f (double x)
{
    return x*x + 2.0;
}

void table (double f(double), double x0, double dx, int n)
{
     cout << setiosflags(ios::fixed)
                 << setiosflags(ios::showpoint)
                 << setprecision(3);
     for (int i=0; i<n; i++)
     {
                cout << "x = " << x0 << " \t f(x) = " << f(x0) << endl;
                x0 += dx;
     }
}


V. Variable scope
Scope refers to the section of a program where an identifier or variable is visible. The
C++ language has two forms of scope: local scope and global scope. For local variables
the scope is the block contained by the brace pair { }. This includes compound
statements and function bodies.

Example: Local scope
# include<iostream>
using namespace std;

void display (void);

int main( )
{
    int a = 5;
    cout << "Before compound statement: a = " << a << endl;

     {
           int a = 10;
           cout << "Inside compound statement: a = " << a << endl;
     }

     cout << "Before function call: a = " << a << endl;
     display( );
     cout << "After function call: a = " << a << endl;

     return 0;
}

void display (void)
{
     int a = 15;
     cout << "Inside display: a = " << a << endl;
}

Global variables are declared outside of every function including main and are accessible
from their point of declaration throughout the remaining portion of the file containing
them with three exceptions.
   1. If a local variable has the same name as a global variable, the global variable can
       be accessed within the scope of the local variable using the global resolution
       operator :: .
   2. The scope of a global variable can be extended into another file using the keyword
       extern (see variable storage classes below).
     3. The same global name can be used in another file as a distinct variable by using
        the keyword static (see variable storage classes below).
It should be noted that the use of global variables is strongly discouraged. Global
variables are considered too visible since they can be changed inside of any function. It
can be very difficult to find errors involving global variables in large programs composed
of many functions.

Example: Global scope
# include<iostream>
using namespace std;

void display (void);
int number = 100;           // global variable

void main( )
{
     int number = 500; // local variable
     cout << "Before function call: number = " << number << endl;
     display( );
     cout << "After function call: number = " << number << endl;
     cout << "Using global resolution operator: number = " << ::number
<< endl;
}

void display (void)
{
     cout << "Inside display: number = " << number << endl;
}

Output
500
100
500
100


VI. Variable storage classes
One could draw a box around the section of code in which a variable is valid in order to
visualize scope. In addition to the spatial concept of scope we can talk about the
temporal concept of a variables lifetime or the length of time a variable can reserve in
memory. There are four storage classes differing in scope and lifetime.
 auto
 static
 extern
 register

Local storage classes
The auto storage class is the default storage class used by C++. As long as a function has
not returned control to the calling function, the local variables are “alive”. When the
function returns control to the calling program the local variables “die”.

# include<iostream>
using namespace std;

void testauto(void);

int main( )
{
    int i;
    for (i = 1; i <= 3; i++)
         testauto( );

     return 0;
}

void testauto(void)
{
     int num = 0;              // local auto variable
     cout << "num = " << num << endl;
     num ++;
     return;
}

output
num = 0
num = 0
num = 0

In the static storage class the local variables remain in existence for the lifetime of the
program. Static variables are useful when you want the function to “remember” values
from one function call to the next. A static variable could be used to keep track of the
number of function calls.

# include<iostream>
using namespace std;

void teststatic(void);

int main( )
{
    int i;
    for (i = 1; i <= 3; i++)
         teststatic( );

     return 0;
}

void teststatic(void)
{
     static int num = 0;                         // local static variable
     cout << "num = " << num << endl;
     num ++;
}
output
num = 0
num = 1
num = 2

The register storage class has the same time duration as auto variables but use a high
speed storage area of the CPU.

Global storage classes

By their nature global variables do not come and go with the calling of any function but
exist until the program is finished executing. Hence there are no global auto or register
variables. The storage classes for global variables affect only the scope and not the
duration. The extern storage class is used to extend the scope of a global variable to
more than one file. The static storage class is used to prevent the extension of a global
variable into another file.

File 1                            File 2
# include<iostream>               double factor;
using namespace std;              extern double volts;
float volts;                      double func2( )
static float power;               {
void main( )                           C++ stuff
{                                 }
     func1( );
     func2( );
     C++ stuff
}

extern double factor;
float func1( )
{
     C++ stuff
}

extern double volts makes the variable volts available to the function in the second file.
This does not create a new variable but merely extends the scope of an existing variable.
extern double factor makes the variable factor available to the func1( ) in the first file.

				
DOCUMENT INFO
Shared By:
Categories:
Stats:
views:38
posted:8/26/2012
language:English
pages:12
Description: Most computer programs used to solve real-world problems are much larger than the programs we have been writing in class. Experience has proven that the best way to develop and maintain a large program is to construct it from smaller pieces or components. Each component is more manageable than the original program and can be developed and tested independently. Functions are one of the constructs used in C++ to develop modular programs.