Rev A Lecture 6

Functions (continued)

 

Exercise 1

Identify the following items in the programming code shown below for parts a and b:

  1. Function prototype, function heading, function body and function definitions.
  2. Function call statements, formal parameters, and actual parameters.
  3. Value parameters and reference parameters.
  4. Local variables and global variables.

 

# include <iostream>                                                       //Line 1

using namespace std;                                                       //Line 2

int one;                                                                              //Line 3

void hello (int&, double, char);                                       //Line 4

void goodbye (int, int);                                                    //Line 5

 

int main()                                                                          //Line 6

{                                                                                        //Line 7

      int x;                                                                           //Line 8

      double y;                                                                     //Line 9

      char x;                                                                         //Line 10

      .

      .

      .

hello(x, y, z);                                                              //Line 11

      .

      .

      .

      hello(x, y-3.5, ‘S’);                                                    //Line 12

      .

      .

      .

}                                                                                        //Line 13

 

void hello( int& first, double second, char ch)               //Line 14

{                                                                                        //Line 15

      int num;                                                                      //Line 16

      double y;                                                                     //Line 17

      int u;                                                                           //Line 18

      int goodbye.

      .

      .

}                                                                                        //Line 19

 

void goodbye( int one, int r);                                           //Line 20

{

 

 

}                                                                                        //Line 21        

Value parameters

When a function is called memory is allocated for its formal parameters and variables declared in the body of the function (called local variables).  A formal parameter that receives a copy of the contents of the corresponding actual parameter is called a value parameter.  That is the value is copied from one memory location, the actual parameter, to another memory location the formal parameter.  Data manipulation on the formal parameter has no effect on the actual parameter’s memory cell.  That is on return from the call, the actual parameter has remained the same.

 

Reference parameter

Utilizing value parameters sometimes has disadvantages.

  1. When the value of an actual parameter has to be changed and one uses a called function.
  2. When you need to return more than one value from a function.
  3. When memory space and time is a premium.

 

The above disadvantages would be removed or reduced if both the actual parameter and the formal parameter shared the same memory space.  Therefore we use what is called the reference parameter.  In this case the formal parameter receives the location (memory address) of the corresponding actual parameter.  To indicate a reference parameter we add the & character immediately after the data type for the formal parameter.

e.g. void convert (int& value1, int& value2.

Note you usually use a void function when you are using reference parameter(s) since there is no need to return a value directly.  Any changes made to the formal parameter(s) in the called function are also done to the active parameter(s) since it is using the same memory space.

 

Do exercise 1c.

 

Exercise 2: What are the outputs of the following program?

 

#include <iostream>

using namespace std;

 

void funcOne (int a, int& b, char c);

 

int main()

{

      int value1, value2;

      char ch;

      value1=5;

      value2=12;

      ch='b';

      cout<<"before calling funcOne the following actual parameters are"<<endl;

cout<<"value1="<<value1<<"  value2="<<value2<<"  ch="<<ch<<endl;

 

funcOne(value1,value2,ch);

 

cout<<"right after calling funcOne the following actual parameters are"<<endl;

cout<<"value1="<<value1<<"  value2="<<value2<<"  ch="<<ch<<endl;

 

return 0;

        }

void funcOne (int a, int&b, char c)

{

     

int numOne = 2;

char chOne = 'T';

a = a + 2;

b = b * 3;

c = 'E';

cout<<"Inside funcOne the following formal parameters are"<<endl;

cout<<"a = "<<a<<"  b = "<<b<<"  c = "<<c<<endl;

cout<<"Inside funcOne the following variables are"<<endl;

cout<<"numOne = "<<numOne<<"  chOne = "<<chOne<<endl;

 

}

 

Use the debugger to see how the code jumps to the function after a call to it.

 

Identifiers are declared within a function heading, within a block or outside of a block.

Local identifiers are identifiers declared within a function ( or block )

Global identifiers are identifiers declared outside of every function definition

 

Do exercise 1d

 

Scope of an identifier

Where in the program an identifier can be accessed from is called its scope.  The rules to determine this are as follows:

  1. Global identifiers are accessible by a function or a block if
    1. The identifier id declared before the function definition (block).
    2. The function name is different from the identifier.
    3. All parameters of the function have names different than the names of the identifier
    4. All local identifiers (such as local variables) have names different than the name of the identifier.
  2. (Nested Block).  An identifier declared within a block is accessible
    1. Only within the block from the point at which it is declared until the end of the block
    2. By those blocks that are nested within that block if the nested block does not have an identifier with the same name as that of the outside block (the block that encloses the nested block).
  3. The scope of a function name is similar to the scope of an identifier declared outside any block.  That is, the scope of a function name is the same as the scope of a global variable.

 

 

Exercise 3

What are the scope of the identifiers in the program of exercise 1?

 

Note you cannot include a function definition within the body of another function!

 

Additional global variable facts

  1. A global variable declared before the definition of a function (block) can be accessed by the function (or block) even it the function (or block) has an identifier with the same name as the variable.  This can be done by the use of a scope resolution operator ::.

Thus if global variable int number is also a variable of the function convert then to access the global variable number from within function convert we at that point use ::number as referring to the global variable and just number as the local one within the function.

  1. To access a global variable declared after the definition of a function we define the variable within the function as

extern data type identifier;

extern int number; 

  1. It is not good to use global variables since they can be accessed by all the functions and a mistake in one can be hard to debug.  On the other hand global named constants are useful to be used since problems do not occur because their value cannot be changed.

 

Exercise 4

 

// Scoping

#include <iostream>

using namespace std;

void func();

int main()

{

               int var=5; // local variable in main()

               cout<<"In main() var is :"<< var<<"\n\n";

               func();

               cout<<"Back in main()var is: "<<var<<"\n\n";

               {

                              cout<<"In main() in a new scope var is:"<<var<<"\n\n";

                              cout<<"Creating new var in new scope.\n";

                             

                              int var=10; //variable in a new scope,hides other variable names var

                             

                              cout<<"In main() in a new scope var is:"<<var<<"\n\n";

               }

               cout<<"At end of main() var created in new scope no longer exists.\n";

               cout<<"At end of main() var is:"<<var<<"\n\n";

               return 0;

}

void func()

{

               int var=-5; //local variable in function

               cout<<"Int func() var is: "<<var<<"\n\n";

}

 

Static and automatic variables

    1. Memory for global variables remain allocated as long as the program executes.
    2. Memory for a variable declared within a block is allocated at block entry and deallocated at block exit.

A variable for which memory is allocated at block entry and deallocated at block exit is called an automatic variable.  A variable for which memory remains allocated as long as the program executes is called a static variable.

When leaving a block the local variables lose their values.  To hold a local variables value you can declare it static.

static data type identifier;

static int number

 

            Function overloading

 

            In a C++ program you can have functions with the same name as long as they

have a different formal parameter list.  This is called function overloading.

a.      A different number of formal parameters in the list

b.     If the number is the same in the parameter list than the data type or the order must differ by at least one.

Therefore when making the function call the actual parameter list will indicate which function is being called.

 

What we have called the function header, function name plus formal parameter list, is called the function signature.  Therefore a function name that has been overloaded contains a set of functions that have different signatures.

 

Functions with default parameters

 

Functions can be called whereby the call with the active parameters are less than the formal parameters in the function header.  This is allowed when there is use of something called default parameters.  You specify the value of a default parameter when the function appears for the first time such as the function prototype.

Example: void funcOne( int a, double b, double c = 45.6);

 

When default parameters are used the following rules are applicable to the function.

a.      If you do not specify the value of a default parameter, the default value is used for that parameter.

b.     All of the default jparameters must be the rightmost parameters of the function

c.      Suppose a function has more than one default parameter.  In a function call, if a value to a default parameter is not specified, then you must omit all of the arguments to its right.

d.     Default values can be constants, global variables, or function call.

e.      The caller tha the option of specifying a value other than the default for any default parameter.

f.      You cannot assign a constant value as a default value to a reference parameter.

 

Exercise 5 Example 7-11 of Malik

 

#include <iostream>

#include <iomanip>

 

using namespace std;

 

int volume(int l = 1, int w = 1, int h = 1);

void funcOne(int& x, double y = 12.34, char z = 'B');

 

int main()

{

      int a = 23;

      double b = 48.78;

      char ch = 'M';

      cout<<fixed<<showpoint;

      cout<<setprecision(2);

      cout<<"a= "<< a<<", b= "

             <<b <<", ch = "<< ch<<endl;

      cout<<" Volume = "<<volume()

             <<endl;

      cout<<" Volume = "<<volume(5,4)

             <<endl;

      cout<<" Volume = "<<volume(34)

             <<endl;

      cout<<" Volume = "<<volume(6,4,5)

             <<endl;

 

      funcOne(a);

      funcOne(a,42,68);

      funcOne(a,34.65, 'Q');

     

      cout <<"a= "<<a<< ", b = "

              << b << ", ch = " << endl;

      return 0;

}

int volume(int l, int w, int h)

{

      return l*w*h;

}

 

void  funcOne(int& x, double y, char z)

{

      x=2*x;

      cout<<"Line 12:x="<<x<< ", y= "

            <<y<< ", z="<< z << endl;

}

 

Solution Exercise 2

 

#include <iostream>

using namespace std;

 

void funcOne (int a, int& b, char c);

 

int main()

{

      int value1, value2;

      char ch;

      value1=5;

      value2=12;

      ch='b';

      cout<<"before calling funcOne the following actual parameters are"<<endl;

cout<<"value1="<<value1<<"  value2="<<value2<<"  ch="<<ch<<endl;

 

funcOne(value1,value2,ch);

 

cout<<"right after calling funcOne the following actual parameters are"<<endl;

cout<<"value1="<<value1<<"  value2="<<value2<<"  ch="<<ch<<endl;

 

return 0;

        }

void funcOne (int a, int&b, char c)

{

     

int numOne = 2;

char chOne = 'T';

a = a + 2;

b = b * 3;

c = 'E';

cout<<"Inside funcOne the following formal parameters are"<<endl;

cout<<"a = "<<a<<"  b = "<<b<<"  c = "<<c<<endl;

cout<<"Inside funcOne the following variables are"<<endl;

cout<<"numOne = "<<numOne<<"  chOne = "<<chOne<<endl;

 

}

 

 

before calling funcOne the following actual parameters are

value1=5  value2=12  ch=b

Inside funcOne the following formal parameters are

a = 7  b = 36  c = E

Inside funcOne the following variables are

numOne = 2  chOne = T

right after calling funcOne the following actual parameters are

value1=5  value2=36  ch=b

Press any key to continue . . .

 

 

Solution Exercise 4

 

// Scoping

#include <iostream>

using namespace std;

void func();

int main()

{

               int var=5; // local variable in main()

               cout<<"In main() var is :"<< var<<"\n\n";

               func();

               cout<<"Back in main()var is: "<<var<<"\n\n";

               {

                              cout<<"In main() in a new scope var is:"<<var<<"\n\n";

                              cout<<"Creating new var in new scope.\n";

                             

                              int var=10; //variable in a new scope,hides other variable names var

                             

                              cout<<"In main() in a new scope var is:"<<var<<"\n\n";

               }

               cout<<"At end of main() var created in new scope no longer exists.\n";

               cout<<"At end of main() var is:"<<var<<"\n\n";

               return 0;

}

void func()

{

               int var=-5; //local variable in function

               cout<<"Int func() var is: "<<var<<"\n\n";

}

 

 

In main() var is :5

 

Int func() var is: -5

 

Back in main()var is: 5

 

In main() in a new scope var is:5

 

Creating new var in new scope.

In main() in a new scope var is:10

 

At end of main() var created in new scope no longer exists

At end of main() var is:5

 

Press any key to continue . . .

 

 

 

Solution Exercise 5

 

#include <iostream>

#include <iomanip>

 

using namespace std;

 

int volume(int l = 1, int w = 1, int h = 1);

void funcOne(int& x, double y = 12.34, char z = 'B');

 

int main()

{

      int a = 23;

      double b = 48.78;

      char ch = 'M';

      cout<<fixed<<showpoint;

      cout<<setprecision(2);

      cout<<"a= "<< a<<", b= "

             <<b <<", ch = "<< ch<<endl;

      cout<<" Volume = "<<volume()

             <<endl;

      cout<<" Volume = "<<volume(5,4)

             <<endl;

      cout<<" Volume = "<<volume(34)

             <<endl;

      cout<<" Volume = "<<volume(6,4,5)

             <<endl;

 

      funcOne(a);

      funcOne(a,42,68);

      funcOne(a,34.65, 'Q');

     

      cout <<"a= "<<a<< ", b = "

              << b << ", ch = " << endl;

      return 0;

}

 

int volume(int l, int w, int h)

{

      return l*w*h;

}

 

void  funcOne(int& x, double y, char z)

{

      x=2*x;

      cout<<"Line 12:x="<<x<< ", y= "

            <<y<< ", z="<< z << endl;

}

 

a= 23, b= 48.78, ch = M

 Volume = 1

 Volume = 20

 Volume = 34

 Volume = 120

Line 12:x=46, y= 12.34, z=B

Line 12:x=92, y= 42.00, z=D

Line 12:x=184, y= 34.65, z=Q

a= 184, b = 48.78, ch = M

Press any key to continue . . .