CSC261 Jan31

slide version

single file version

Contents

  1. Call by Value
  2. Call by Reference
  3. How to Specify the Calling Method: Value or Reference
  4. Syntax of Passing Arguments to a Function
  5. Which Calling Method?
  6. Declarations for Call By Value/Reference
  7. Input and Call by Reference
  8. The getInput Function
  9. Call by Constant Reference
  10. Functions
  11. Argument Passing and Multiple Arguments
  12. Declaration of setBoth
  13. Overloading Functions
  14. Overload Resolution
  15. Example
  16. Overloaded Resolution (is tricky in C++)
  17. Default Arguments

Call by Value[1] [top]

All these predefined functions have parameters passed by value.

If we call one of these functions, no change occurs to the argment:

int main()
{
    double x = 5.0;

    double y = sqrt(x);

    // x is still 5.0!!

Call by Reference[2] [top]

How to Specify the Calling Method: Value or Reference[3] [top]

The default calling method is call by value.

     void swap(int x, int y);

Here arguments will be passed to x and y by value.

To specify call by reference place an & (an ampersand) after the parameter type in the function declaration (and definition).

     void swap(int& x, int& y);

Syntax of Passing Arguments to a Function [4] [top]

There is NO difference in the syntax of calling a function if its parameters are call by value or call by reference.

The compiler has to see the declaration of the function being called to determine how to pass the arguments.

The programmer writes the same sytnax for the call in either case.

Are arguments a and b passed by value or reference by the following code? You can't tell unless you see the declaration of the swap function.

int main()
{
   int a = 5, b = 10;

   swap(a,b);

   cout << a << b << endl;

   return 0;
}

Which Calling Method?[5] [top]

Which calling method should be used for the function in these function calls:

int main()
{
  int a, b, c;
  int max;
  double avg;

  cin >> a >> b >> c;
  sort(a,b,c);
  max = findmax(a,b,c);
  avg = average(a,b,c);

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

  cout << "Max = " << max << endl;
  cout << "Average = " << avg << endl;
  return 0;
}

What should the declarations be for each of these functions?

Declarations for Call By Value/Reference[6] [top]

   void sort(int&, int&, int&);
   int findmax(int, int, int);
   double average(int, int, int);

Input and Call by Reference[7] [top]

In the previous example there was no prompt to the user to enter the input.

Suppose we decide we want to modify the code like by adding a function getInput to read in the three value like this:

int main()
{
  int a, b, c;
  int max;
  double avg;

  getInput(a,b,c);
  sort(a,b,c);
  max = findmax(a,b,c);
  avg = average(a,b,c);

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

  cout << "Max = " << max << endl;
  cout << "Average = " << avg << endl;
  return 0;
}

What should the declaration for getInput be? (Should it use call by value or call by reference?)

The getInput Function[8] [top]

Declaration

void getInput(int&, int&, int&);

Definition

  void getInput(int& x, int& y, int& z)
  {
    cout << "First number: ";
    cin >> x;
    cout << "Second number: ";
    cin >> y;
    cout << "Third number: ";
    cin >> z;

  }

What would happen in the main program if getInput used call by value?

Call by Constant Reference[9] [top]

Call by constant reference isn't really a different argument passing method.

It is just call by reference

It combines the const qualifier with the parameter type declaration and has the usual meaning.

A parameter that is declared to have values passed by constant reference

Syntax Example

Call by constant reference:

     int findMax(const int& a, const int& b, const int& c);

We could instead declare findMax to use call by value:

     int findMax(int a, int b, int c);

What is the difference between call by value and call by constant reference?

Functions[10] [top]

A function that has a return type of void must have some effect such as input, output, or modification of the arguments.

A function that has a non void return type should typically not have side effects. It is like an operator that produces some new result but doesn't change its operands.

Argument Passing and Multiple Arguments[11] [top]

Argument passing method can be different for each argument in a function that has multiple parameters.

The function setBoth below sets a = x and b = y and guarantees that x and y are not changed!

What should its declaration be? That is, how should the 4 arguments be passed?

int main()
{
   int a = 5, b = 3;
   int x, y;
   x = a + b;
   y = a;

   setBoth(a, b, x, y);

}  

Declaration of setBoth[12] [top]

The first two arguments must be passed by reference.

The second two could be passed by value or constant reference to guarantee that the third and fourth arguments are not changed

    void setBoth(int& aval, int& bval, int xval, int yval);

or

    void setBoth(int& aval, int& bval, const int& xval, const int& yval);

Overloading Functions[13] [top]

Here is the getInput function again, but it changed to explicitly ask for an integer:

  void getInput(int& x, int& y, int& z)
  {
    cout << "First integer: ";
    cin >> x;
    cout << "Second integer: ";
    cin >> y;
    cout << "Third integer: ";
    cin >> z;

  }

Suppose we also wanted a function to read 3 values of type double.

Just modify getInput like this:

  void getInput(double& x, double& y, double& z)
  {
    cout << "First double: ";
    cin >> x;
    cout << "Second double: ";
    cin >> y;
    cout << "Third double: ";
    cin >> z;

  }

Can you have both functions (with the same name!!) in the same program?

In C++, yes. (In C the answer was no.)

Overload Resolution[14] [top]

If there are two functions named the same (e.g. getInpt), the function is said to be overloaded.

If an overloaded function is called, the compiler must determine which version is being called.

This is called overload resolution.

Example[15] [top]

Here are the declarations for the two versions of getInput

  1. void get(int&, int&, int&);
  2. void get(double&, double&, double&);

Which version should be called (1 or 2) for each of the following calls:

    int a, b, c;
    double x, y, z;
    float p, q, r;

    getInput(a,b,c);  // A. 
    getInput(x,y,z);  // B.
    getInput(p,q,r);  // C

Overloaded Resolution (is tricky in C++)[16] [top]

Here is the same example, except that suppose the double version of getInput is changed to float:

Here are the declarations for the two versions of getInput

  1. void get(int&, int&, int&);
  2. void get(float&, float&, float&);

Which version should be called (1 or 2) for each of the following calls:

    int a, b, c;
    double x, y, z;
    float p, q, r;

    getInput(a,b,c);  // A. 
    getInput(x,y,z);  // B.
    getInput(p,q,r);  // C

Default Arguments[17] [top]

Functions can specify default argument values in the function declaration.

If a default argument value is given in a function declaration, the caller can override the default value by passing an argument.

But if the caller omits the argument altogether, the default argument value is used.

double area(double radius = 1.0 );

int main()
{
  double a1, a2;
  double r;

  cin >> r;

  a1 = area(r);  // radius = r
  a2 = area();   // radius = 1.0

}
double area(double radius) 
{
  return radius * radius * PI;
}