Functions

Why Write Functions?

  • Divide-and-conquer:  Break programs into smaller, more manageable pieces
  • Reusability
  • Avoid repetition of code in a program

  •  

    Function Stages

    1)  Declaration - a function declaration, or prototype, consists of three things:
  •  name
  •  return type (the type of the value that the function will return.  Use void if no value returned.)
  •  parameter list (number of parameters and their types, in a comma-separated list)

  • Declaration (Prototype) Format:

      return-type function-name( parameter-list );
    

    Examples:

      // Good function prototypes 
      double Average(double x, double y); 
      double Average(double, double); 
      char GetACharacter(); 
      void PrintValues(int count, double amount); 
    
      // BAD prototypes 
      double Average(double x, y);  // Each parameter must list a type 
      PrintData(int x);             // missing return type 
      void Calculate()              // missing semicolon 
    

    2)  Definition - a function definition repeats the declaration, and adds to it a function body. The body is the code that is implemented when the function is called.

    Definition Format:

      return-type function-name( parameter-list ) 
      { 
         function-body (declarations and statements) 
      } 
    

    Note that variables in the parameter-list, along with any variables declared inside the function body, are local variables.  They only have scope within the function definition itself.

    To return a value (from a function with a non-void return type), use the keyword return:

      return expression;
    

    The keyword return can also be used in a void function, to force early exit.  In this case, use it by itself:

      return;
    

    A return statement will force immediate exit from the function, and it will return the value of the expression to the caller.
     

    3)  Call - a function call is a command to execute a function. A call must use the function name and must pass in appropriate arguments. Return values must be used correctly.

    In keeping with the "declare before use" policy, a function call can be made ONLY if a declaration (or definition) of the function has been seen by the compiler first.
     

    Example:

      int Sum(int x, int y);     // declaration (ends with semi-colon) 
    
      int Sum(int x, int y)      // Here is the definition (no semi-colon after header) 
      { 
         return (x + y); 
      } 
    
      int main() 
      { 
         int a = 5, b = 7, c; 
         c = Sum(a, b);          // function call, assigning return value to c 
      } 
    
    

    Important:  Function calls must agree with the expected types in the function declaration (prototype).  Also, the function definition must match the function prototype.
     

    Example 1 -- Program with function calls.
    Example 2 -- Function call example with good and bad function calls.
     


    Default parameters:

    C++ adds in the ability to use default parameters. Essentially these are optional parameters that are given default values when the function is declared.
    Rule: Regular parameters must come first in the parameter list, and defaults must be at the end.

    Examples:

     int Compute(int x, int y, int z = 5); 
     double RunAround(char x, int r = 7, double f = 0.5); 
    
     double Jump(int a, int b = 2, int c);          // This one is illegal. Why? 
    

    Using the first example above, the function calls in the following code segment would both be legal:

     int a = 2, b = 4, c = 10, r; 
    
     cout << Compute(a, b, c); 
     r = Compute(b, 3); 
    

    Notice that the first call to the Compute function passes three arguments.  The second call only passes two.  Since no third argument was passed, the third parameter of the Compute function (z) will take it's default value (5).
     


    Function Overloading

    The term function overloading refers to the fact that it is perfectly legal to have more than one function in the same scope, with the same name, as long as they have different parameter lists.

    The combination of a function's name and it's parameter list is often known as the function signature. Using this definition, two functions in the same scope are considered different (and distiguishable by the compiler) if they have different signatures.

    Example:

       int Process(double num);		  // function 1
       int Process(char letter);              // function 2
       int Process(double num, int position); // function 3
    
    Notice that although all three functions have the same exact name, they each have a different parameter list. Some of them differ in the number of parameters (2 parameters vs. 1 parameter), and the first two differ in types (double vs. char). The compiler will distinguish which function to invoke based on what is actually passed in when the function is called.
       x = Process(3.45, 12);	// invokes the third function above
       x = Process('f');		// invokes the second function
    

    Worth noting, also, is that a function that uses default parameters can count as a function with different numbers of parameters. For example, if we declare:
       int Process(double x, int y = 5);
    
    this function would conflict not only with function 3 above (which already takes a double and an int), but it also conflicts with function 1 above, since we could invoke this one by just passing in a single parameter (the double).