·        Predefined Functions – Functions that come out of the C++ Libraries.  Make sure you include the header file that has the function prototype (declaration).

o       Predefined Functions That Return a Value – A function that performs an action and returns a value.

 

#include <iostream>

#include <cmath>

using namespace std;

 

int main()

{

double result, a = 2, b = 3;

 

result = pow(a, b);

cout << “Result = ” << result << endl;

 

return 0;

}

 

o       Predefined void Functions – A function that performs an action, but does not return a value.

 

#include <iostream>

#include <cstdlib>

using namespace std;

 

int main()

{

      cout << “Exiting with an error code.\n”;

      exit(0x2ab);

       cout << “We will never reach this point in the code.\n”;

     

return 0;

}

·        Programmer-Defined Functions – These are functions that are defined by the programmer.  The declarations for the functions should be placed into a .hpp header file.

 

o       Defining Functions that Return a Value

 

// Generic prototype that is put into a header file

<return type> functionName(<param_type> param1, <param_type param2, etc …);

 

// A sample function prototype (located in interest.hpp file)

double interestEarned(double principal, double rate, int numberYears);

 

// The function implementation (located in interest.cpp file)

#include <iostream>

#include <cmath>

using namespace std;

 

////////////////////////////////////////////////////////////////////////////////

//        interestEarned()  

//

//        Description:        This function will return the interest   

//                                  on a loan or investment for a given period of time. 

//                                  The formula used for calculating the compounded

//                                  interest is based upon the following conditions:

//

//                      P = original principal amount

//                      I = annual interest rate (in decimal form)

//                      N = number of compounding periods per year

//                      Y = number of years

//                      T = total of principal and interest to date

//

//                      The general formula for compound interest calculation

//                      can be written as

//

//                                  T = P ( 1 + I / N )^YN

//

//        Inputs:                principal

//                                  rate

//                                  numberYears

//

//        Outputs: none

//

//        Return:               interest

/////////////////////////////////////////////////////////////////////////////////

double interestEarned(double principal, double rate, int numberYears)

{

            double totalAmount, interest;

           

totalAmount = principal * pow((1 + (rate/100)),

static_cast<double>(numberYears));

            interest = totalAmount - principal;

 

            return interest;

}

 

 

 

// The driver function implementation (located in example.cpp)

#include <iostream>

#include "interest.h"

using namespace std;

 

int main()

{

            double principal, rate, interest;

            int numberYears;

 

            cout << "Enter principal, interest rate, and number of years: ";

            cin >> principal >> rate >> numberYears;

 

            interest = interestEarned(principal, rate, numberYears);

            cout.setf(ios::fixed);                   // Floats as fixed points

            cout.setf(ios::showpoint);           // Always show decimal point

            cout.precision(2);                      // Number decimal digits

            cout << "You've earned $" << interest << " in interest.\n";

 

            return 0;

}

         

o       Alternate Form for Function Prototype

 

Be aware that both function declarations may have the variable identifier or may simply have the type (no identifier).

 

double interestEarned(double principal, double rate, int numberYears);

or

double interestEarned(double, double, int);

 

This is only true for the function prototype (declaration).  Formal parameters must be listed in the actual function definition.

 

o       Functions Calling Functions – When functions call other functions, whether user-defined or not, it is important that the calling function know the function prototype or function definition of the function it is calling.

 

o       Functions that Return a bool Value – A function that may take formal parameters, but returns a Boolean true/false value to the calling function.

 

#include <iostream>

using namespace std;

 

bool checkRange(int value, int min, int max)

{

            if((value >= min) && (value <= max))

                        return true;

            else

                        return false;

}

 

int main()

{

            int value;

 

            cout << "Enter a value: ";

            cin >> value;

 

            if(checkRange(value, 0, 100))

                        cout << "In range.\n";

            else

                        cout << "Out of range.\n";

 

            return 0;

}

 

o       Defining void Functions – Void functions may take formal parameters but do not return a value.  The call to the void function is coded on a single line much like a statement and is not used in arithmetic expressions as a variable or non-void function might be.

 

#include <iostream>

using namespace std;

 

void displayCopyright()

{

            cout      << "Copyright (c) 2002\n"

                        << "All rights Reserved\n\n";

}

 

int main()

{

            displayCopyright();

 

            return 0;

}

 

o       Return Statements in void Functions – A return statement may be placed in a void function if it is desirable to leave the function for a given condition.  The return statement is written on a line by itself without anything to return:

 

void someFunction(int arg1)

{

            int number;

           

// do some stuff

 

            if(!number)

                        return;

 

            // do some more stuff if number was found to be non-zero

}

 

o       main Function – The main() function, as we know by now is the function is automatically called when a program is run.  It may, in turn, call other functions.  The main function should not call itself recursively.  The main() function traditionally returns type int.

 

·        Scope Rules

o       Local Variables – Local Variables are variables that are local to a particular function and are not accessible outside of that function.  Two functions may have local variables with the same name, but they are not the same variable and do not occupy the same memory space.

o       Procedural Abstraction – Writing “black box” code.  We don’t need to know how a function does something; we only need to know what the function actually does.

o       Global Constants and Global Variables – Constants (initialized) and Variables (initialized or non-initialized) declared outside the body of all function definitions are global to all functions following the declaration within the given file.

§        Try to keep the global constants grouped together for better readability.

§        Global Variables – Try to avoid using as much as possible.  It makes code confusing and error-prone.

o       Blocks – A pair of curly braces is called a compound statement.  A compound statement that has declarations is called a block.  The declarations are within the scope of the block.

 

#include <iostream>

using namespace std;

 

int main()

{

            int num1 = 3, num2 = 4;

           

            // Result below will be 3

            cout <<"Num1 in main() before block = " << num1 << endl;

            // Result below will be 4

            cout <<"Num2 in main() before block = " << num2 << endl;

 

            // Below is a new block within the curly braces

{

                        int num1 = 500, num3 = 50;

                       

                        // Result below will be 500

                        cout <<"Num1 in block = " << num1 << endl;

                        // Result below will be 4

                        cout <<"Num2 in block = " << num2 << endl;

                        // Result below will be 50

                        cout <<"Num3 in block = " << num3 << endl;

            }

 

            // Result below will be 3

            cout <<"Num1 in main() after block = " << num1 << endl;

            // Result below will be 4

            cout <<"Num2 in main() after block = " << num2 << endl;

 

            return 0;

}

 

o       Nested Scopes – Blocks within blocks have nested scopes.  The variables declared within a particular block are not within the scope of the outer block(s).

o       Variables Declared in a for Loop – A variable declared in the for loop initialization is treated as if it were local to the for loop.  Older compilers will treat this differently, so be careful.  This is now an ANSI/ISO requirement for the C++ Standard.

 

·        Parameters – C++ Allows you to make function calls with Call-by-Value and Call-by-Reference Parameters

o       Call-by-Value Parameters – We have been doing Call-by-Value thus far. 

§        Call-by-Value parameters are just like local variables that you declare within the body of a function.  The arguments of a function call are copied into the formal parameters of the called function and are not affected by changes made to the formal parameters within the called function.

o       Call-by-Reference Parameters – Call-by-reference is accomplished by appending an & to the type name.

§        Call-by-Reference parameters are variables; not constants or expressions.

§        The arguments of a function call are substituted for the formal parameters of the called function and are affected by changes made within the called function.

§        Call-by-Reference formal parameters are placeholders for the actual arguments used in a function call.

 

// Consider the following prototype

void getNumbers(int& num1, int& num2, int& num3);

 

// Consider the calling of the function

int first, second, third;

getNumbers(first, second, third);

 

·        When the function is called, the function is given the list of memory locations associated with each name.  Each memory location is associated with the corresponding formal parameter.

 

first àAddress of first à num1

second àAddress of second à num2

third àAddress of third à num3

 

o       Constant Reference Parameters – We will skip this for now, but be aware that this will be helpful later on in the course when we discuss arrays and classes.

o       Mixed Parameter Lists – We can mix Call-by-Value and Call-by-Reference parameters in the function prototype and function definition.

 

// The following prototype is legitimate.

void getNumbers(int& num1, int num2, int& num3, int& num4);

 

§         Be aware that num2 will be a local variable to getNumbers().  If you had meant to call-by-reference for all numbers, then num2 would be called an inadvertent local variable and the function would not work as intended.

 

 

 

 

 

 

Parameter

How the Parameter Type is Used

Call-by-Value

Only the value of the argument is used.  The formal parameter is a local variable that is initialized to the value corresponding to the argument.

Call-by-Reference

The argument is a variable. The argument variable is substituted for the formal parameter and any change made to the formal parameter is actually made to the argument variable

 

 

·        Overloading and Default Arguments

o       Overloading – C++ Allows multiple different definitions to the same function name.  The function definitions must have different numbers of formal parameters or some formal parameters of different types.

§        Cannot overload a function name by giving two definitions that differ in the return type.

§        Cannot overload a function name based solely on const

§        Cannot overload a function name based solely on call-by value versus call-by-reference.

 

// Example by giving the declarations

void fun(int num1);

void fun(double num1);

void fun(int num1, int num2);

void fun(int num1, int num2, char answer);

 

// The function definitions would implemented according to the

// function declarations shown above.  For example:

#include <iostream>

using namespace std;

 

void fun(int num1)

{

        cout << “Called function taking one integer.\nnum1 = ” << num1 << endl;

}

 

void fun(int num1, int num2, char answer)

{

        cout        << “Called function taking two ints and a char.”

<< “\nnum1 = ” << num1 << “\nnum2 = ” << num2

<< “\nanswer = ” << answer << endl;

}

 

int main()

{

        fun(6);

fun(6, 15, ‘y’);

 

return 0;

}

                               

§       The overloaded function’s signature is the function’s name with the sequence of types in the parameter list, not including the const keyword and not including the ampersand.  The overloaded functions each have different signatures that the compiler uses for calling the correct function.

 

o       Rules for Resolving Overloading

§        The first rule is to look for an exact match.  If the number and types of arguments is an exact match to the formal parameters in the function, then this rule is satisfied.

§        Type-Conversion Match.  The C++ compiler will do an automatic type-conversion when needed.  If the first rule isn’t satisfied, then this rule is used.

·        Caution:  It is best to program exclusively with the first rule in mind.  The following example will cause a compiler error.

void f(int n, double m);

void f(double n, int m);

 

f(4, 5);  // Cannot determine which function to use

f(4., 5.);// Cannot determine which function to use

 

o       Default Arguments – Default values can be assigned to the formal parameters of overloaded functions.  Default values must be ordered from right to left in the function declaration.  Default values are not put in the function definition.

 

// Example by giving the prototypes

void fun(int num1 = 100);

void fun(int num1, int num2, char answer = ‘n’);

 

#include <iostream>

using namespace std;

 

void fun(int num1)

{

        cout << “Called function taking one integer.\nnum1 = ” << num1 << endl;

}

 

void fun(int num1, int num2, char answer)

{

        cout        << “Called function taking two ints and a char.”

<< “\nnum1 = ” << num1 << “\nnum2 = ” << num2

<< “\nanswer = ” << answer << endl;

}

 

int main()

{

        fun();

fun(6);

fun(10);

fun(10, 20);

fun(6, 15, ‘y’);

 

return 0;

}

 

// The output is shown below.

Called function taking one integer.

num1 = 100

Called function taking one integer.

num1 = 6

Called function taking one integer.

num1 = 10

Called function taking two ints and a char.

num1 = 10

num2 = 20

answer = n

Called function taking two ints and a char.

num1 = 6

num2 = 15

answer = y

 

·        Testing and Debugging Functions

o       The assert Macro – Used like a function that takes a call-by-value parameter of type bool.  It evaluates the assertion argument.  If it equates to false, the program ends and an error message is issued; otherwise, nothing is done and the program continues.  Must use the cassert header file to use the macro.

 

#include <iostream>

#include <cassert>

using namespace std;

 

int main()

{

            int number;

 

            for(int i = 0; i < 2; i++)

            {

                        cout << "Enter a number that is not zero:  ";

                        cin >>number;

 

                        assert(number != 0);

                        cout << "You entered " << number << endl;

            }

 

            return 0;

}

 

// The output is shown below

Enter a number that is not zero:  15

You entered 15

Enter a number that is not zero:  0

Assertion failed: number != 0, file c:\class\practice.cpp, line 263

 

o       Stubs and Drivers – Stubs and Drivers are useful for building larger programs and testing functions

§        Stub functions are functions whose definition will be coded at a later time and used in a larger program. They are coded to provide information to other functions during the development of a larger, integrated program.

§        Driver functions are functions that are specifically designed to test other functions.  They are good for trying to “break” code in the development process.  Once a function has been fully tested by a driver function, the likelihood that it will cause a problem in the larger, integrated program is reduced.

Hosted by www.Geocities.ws

1