Contents  1-5  6-11  12-16  17-21  22-27   28-33  34 - 38  39-46  Projects   MFC

   Contact
   Search
   C
   C++
   Visual Basic
   Java
   JavaScript
   DHTML
   Style Sheets
   About
   Active X
   TDC Binding
   PHP
   Perl and CGI
   Flash
   XML
   SQL
   Messages
   Chat
   MCSE
   Linux
   Cabling   
   ActionScript
   Downloads
   E-Cards   
 
    
    

Note: Updated!  See top of introduction page c1.html for using a C++ .Net compiler for these standard C++ tutorials.

Functions are subprograms (subroutines) within a larger program that can act on data and return a value.  A well
designed function performs a specific task and then returns a value.  Complicated tasks can be broken  down into
multiple functions and then each can be called in turn.  This makes it possible to break up a large and complex
program into smaller, more manageable pieces. 
In C++ there are three necessary steps to take in order to use a
function.  A function must be:  1) Declared (prototyped) before it is called,  2) Called (invoked) from within main() or another function or class, and 3) Defined (implemented) with all of its code placed between brackets.  If the program consists of only one file and the function is defined before it is called in the same file, then the prototype/declaration step can be skipped and the first stage omitted entirely.  If the program consists of multiple files and classes, however, and there is a chance the function will be called before it is defined, then it MUST be prototyped/declared.  The compiler needs a "heads up" in case the function gets called before the compiler encounters its definition.

"The opposite of a correct statement is a false statement. The opposite of a profound truth may well be another profound truth." - Niels Bohr

Let's review:

1. Declaration
- The declaration (prototype) tells the compiler the name, return type and parameters of the function.  The declaration of a function is called its prototype.  No function can be called from any other function that hasn't first been declared unless it has already been defined.  While this step can be omitted in small programs, it becomes a necessity in larger ones with multiple files.   The prototype will contain the return type, arguments and parameters, and unlike the definition, must terminate with a semicolon.  No function code goes in the prototype, only the function header.

2. Call - The call (invocation) actually activates the function, calling its subroutines into action.  Arguments can be passed and values returned.

3
. Definition - The definition (implementation) tells the compiler how the function works.  It consists of all the function's code, nested between brackets.

Built-in functions with their prototypes already written are included with your compiler.  Just  "#include"  the appropriate file and you're good to go.  The function prototype is a statement, so it ends with a semicolon.  It consists of the function's return type, name, and parameter list.  The function prototype and the function definition must agree exactly about the return type.  If they do not agree you will get a compile-time error.  The function prototype does not need to contain the names of the parameters, just their types. Example:   long Area (int, int);

This prototype declares a function named Area() that returns a long and that has two parameters, both integers.  Adding names makes the function prototype clearer: long Area (int length, int width);  Example:

#include <iostream.h>

int ComputeArea(int length, int width);
//1. function prototype

int main()
{
  int GardenLength;
  int GardenWidth;
  int GardenArea;
  cout << "\nHow wide is your garden? ";
  cin >> GardenWidth;
  cout << "\nHow long is your garden? ";
  cin >> GardenLength;

  GardenArea = ComputeArea(GardenLength,GardenWidth);
//2. calling function

  cout << "\nYour garden is ";
  cout << GardenArea;
  cout << " square feet.\n\n";

  return 0;
 }

int ComputeArea(int l, int w)
//3. DEFINITION of function
{
    return
l * w;
}

Output:

How wide is your garden?   100
How long is your garden?    200
Your garden is 2000 square feet.

Prototype Examples:

long ComputeArea  (long length,  long width);           //returns long, has two parameters
void PrintAMessage (int messageNumber);            
 //returns void, has one parameter
int GetUserChoice();                                            
 //returns int, has no parameters

You can pass in global variables to the function, or you can declare variables within the function locally.  When you pass a value to a function as an argument or parameter and do not use pointers or references, you are passing by value.  A copy of the object being passed is created and presented to the function.  What is done to the copy in the function does not effect the original in the global namespace object outside the function.  By default, variables inside a function exist locally, only within the function where they are assigned.  When that function ends its objects are destroyed and its variables abandoned to free memory.  For this reason, passing by value is not as efficient as passing by reference, since each object passed as an argument or parameter must create a copy and thus consume twice as much memory.

Scope - Scope determines how long a variable is available to your program and where it can be accessed.  In C++ it can be local or global.

Global variables
- Global variables are defined outside of a function and thus available to any function in the program - including main().  In C++ too many global variables should be avoided because they create confusing code that is hard to maintain and impair the efficiency of memory.

Function statements
- There are no limit to the number of statements you can have in a function, but keep them small and concise.   Encapsulation and data-hiding principles should be practiced adhered to.

Function arguments
- Function arguments do not have to be of the same type.  You can write a function that takes an integer, two longs, and a character as its arguments.  Any valid C++ expression can be a function argument including constants, mathematical and logical expressions, and other functions that return a value.

May you use functions as parameters to other functions? - Yes, you can, but it makes for poorly maintained code.

Answer = (double(triple(square(cube(myValue)))));

This takes the variable "myValue" and passes it to the function "cube" whose return value is passed as an argument to the function "square", and so on and so on.  A better way would be:

unsigned long myValue = 2;
unsigned long cubed = cube(myValue);        
//a cubed function renders 8
unsigned long squared = square (cubed);    
 //a square function renders 64
unsigned long tripled = triple (squared);    
//a tripled function renders 192
unsigned long Answer = double(tripled)      
//a double function renders 384

Remember, parameters when passed by value are LOCAL variables.  The arguments passed into the function are local to the function.   Changes made to the arguments do not affect the values in the calling function.  Example:

#include <iostream.h>


//1. Function prototype
void SwapIntegers(int x, int y);

//----------------------------------------------------------------------------------------------------------------

int main()
{
    int x = 5, y = 10;
    cout << "Main. Before SwapIntegers, x: " << x << " y: " << y << "\n";
 
   
//2. Function call
    SwapIntegers(x,y);

    cout << "Main. After SwapIntegers, x: " << x << " y: " << y << "\n";

    return 0;
}

//----------------------------------------------------------------------------------------------------------------

//3. Function definition
void
SwapIntegers(int x, int y)
{
     int temp;

     cout << "SwapIntegers. Before SwapIntegers, x: " << x << " y: " << y << "\n";

     temp = x;
     x = y;
     y = temp;

     cout << "SwapIntegers. After SwapIntegers, x: " << x << " y: " << y << "\n";
}

Note: All values in "SwapIntegers()" are local and are not passed outside the function.  Hence the confusion.  Output:

Main.  Before SwapIntegers.  x: 5    y: 10
SwapIntegers.  Before SwapIntegers.  x: 5    y: 10
SwapIntegers.  After SwapIntegers.  x: 10  y: 5
Main.  After SwapIntegers.  x: 5    y: 10

The parameters passed in to the SwapIntegers function are passed by value, meaning that copies of the values are made that are local to SwapIntegers().  These local variables are swapped in the function but the variables back in main() are unaffected.  Note:

return values
- functions must return values or return void.
void - a signal to the compiler that no value will be returned.

Note:  To return a value from a function, write the RETURN keyword followed by the value you want to return.  Examples:

return 5;         return (x > 5); 

The second example will be 0 (false) if x<=5 or 1 (true) if x>5.  value of the expression - true/false - is returned, not value of x.  You can also call a function and pass its return value in as the return value of another function.  Example:

return (MyFunction());

When the return keyword is encountered the expression following it is returned as the value of the function.  Program execution returns immediately to the calling function and any statements following the return are not executed.  It is legal to have more than one return statement in a function, but the problem is, as soon as a return statement is executed, the function ends.  For example:

#include <iostream.h>

int TripleIntegers(int AmountToTriple);

//----------------------------------------------------------------------------------------------------------------

int main()
{
    int result = 0;
    int input;
    cout << "Enter a number between 0 and 10,000 to triple: ";
    cin >> input;

    cout << "\nBefore TripleIntegers is called... ";
    cout << "\ninput: " << input << " Tripled: " << result << "\n";

    result = TripleIntegers(input);

    cout << "\nBack from TripleIntegers...\n";
    cout << "\ninput: " << input << "   Tripled: " << result << "\n";
 
    return 0;
}

//----------------------------------------------------------------------------------------------------------------

int TripleIntegers(int original)
{
    if(original <= 10000)
        return original * 3;
    else
        return
-1;
 
    cout << "You can't reach this line! The function returns 1st.\n"; 

}


Output =
Enter a number between 0 and 10,000 to double: 9000
Before TripleIntegers is called...
input: 6000   tripled: 0
Back from TripleIntegers...
input: 6000  doubled: 18000

Parameters - For every parameter declared in a function prototype and definition, the calling function must pass a value.  The value passed in must be of the declared type.  If you have a function declared:

long myFunction(int);

The function must in fact take an integer variable and return a long.  If the function definition differs or if you fail to pass in an integer you will get a compiler error.  Default parameters are the ONLY exception to this rule.  If the function prototype declares a DEFAULT VALUE FOR THE PARAMETER, then it may be called without passing a value in for that parameter.  It is a value to be used if none is supplied.  Example:

long myFunction (int = 50);

This prototype says "myFunction()" returns a long and takes an integer parameter.  If an argument is not supplied, use the default value of 50.  The header would be:

long myFunction (int x);

If the calling function did not include a parameter, the compiler would fill x with the default value of 50.  The name of the default parameter need not be the same as the name of the function header.  The default value is assigned by position, not name.  Any or all of the function's values can be assigned default parameters.  However, if any of the parameters DO NOT HAVE A DEFAULT value, no previous parameter may have a default value.  Example:

long myFunction (int Param1=7, int Param2=6, int param3=5);

You can assign a default value to Param2 only if you have assigned a default value to Param 3.  You can assign a default value to Param1 only if you have assigned default values to both Param2 and Param3:
 

#include <iostream.h>

int ComputeArea(int length, int width = 25, int height = 1);

//----------------------------------------------------------------------------------------------------------------

int main()
{
    int length = 100;
    int width = 50;
    int height = 2;
    int area;

    area = ComputeArea(length, width, height);

    cout << "First area equals: " << area << "\n";
    area = ComputeArea(length, width);
    cout << "Second time area equals: " << area << "\n";
    area = ComputeArea(length);
    cout << "Third time area equals: " << area << "\n";

    return 0;
}

//----------------------------------------------------------------------------------------------------------------

ComputeArea(int length, int width, int height)
{
         return (length * width * height);
}


Output=
First area equals: 10000
Second time area equals: 5000
Third time area equals: 2500

The prototype AreCube() specifies that the ComputeArea() function takes 3 integer parameters.  the last 2 have default values.  it computes the area of a cube whose dimensions are passed in.  If no width is passed in, a width of 25 and a height of 1 is used.  If the width but not height is passed, a height of 1 is used.  It is not possible to pass in the height without passing in the width.

Overloading functions - Overloading functions involves creating more than one function with the same name.  The functions must differ in their parameter list, with a different type of parameter, a different number of parameters, or both.  It is also called function polymorphism, you can overload a function with more than one meaning.

int myFunction(int, int);
int myFunction(long, long);
int myFunction(long);

myFunction() is overloaded with 3 different parameter lists.  Suppose you want to write a function to double whatever input you give it.  You wan t to pass in an int, long, float, or a double.  Without function overloading you'd have to create 4 separate function names:

int DoubleInt (int);
long DoubleLong (long);
float DoubleFloat (float);
double DoubleDouble (double);

With function overloading you make this declaration easier to read and use.  We don't have to worry about which function to call later on, just pass the right variable and the right function is called automatically based on its data type:

int DoubleNum(int);
long DoubleNum(long);
float DoubleNum(float);

Inline functions -  Inline functions are not real functions, the compiler reads the code of inline function each time into the program.  This can slightly increase a program's speed by not causing the program to stop executing, find the function and then resume.  However, the tradeoff is that it will greatly increase the executable's size.  Small function's are candidates for inline functions, but WHEN IN DOUBT LEAVE IT OUT.

#include <iostream.h>

inline int Quadrupler(int);

int main()
{
    int target;
    cout << "Enter a number to work with:";
    cin >> target;
    cout << "\n";

    target = Quadrupler(target);

    cout << "Target: " << target << endl;

    target = Quadrupler(target);

    cout << "Target: " << target << endl; 
    target = Quadrupler(target);
    cout << "Target: " << target << endl; 
 
    return 0;
}

 
int Quadrupler (int target)
{
    return 4 * target;
}   


Output=
Enter a number to work with: 20
Target: 40
Target: 80
Target: 160


It is the same as if you had written target=2*target; everywhere you entered
target=Quadrupler(target);   This saves a jump in the execution of the code in the object file, at the expense of a larger program.

The stack - The stack is created by the compiler when a program begins.  It is a last in, first out queue, like a stack of dishes in a cafeteria.  It is a special area of memory allocated for your program to hold the data allocated by each of the functions in your program.  When data is pushed on the stack it grows, when it is taken off it shrinks.  A more accurate picture is a series of cubby holes.  The top of the stack is whatever the stack pointer happens to be pointing to. Each cubby has a sequential address and one of those addresses is kept in the stack pointer register. Everything below that pointer/address known as the top of the stack is considered to be on the stack.  Everything above it is considered off the stack and invalid. 

When the program calls a function, a stack frame is established.  This is an area of the stack set aside to manage that function. The steps are:

1. The return address of the function is put on the stack.  When the function returns it will resume executing at this address.
2. Room is made on the stack for the return type that you've declared.
3. All the arguments to the function are placed on the stack.
4. The program branches to your function.
5. Local variables are pushed onto the stack as they are defined.
 


©2004 C. Germany