Section 3 - Parameters and Arguments

5B.3.1  Passing Arguments to Methods

There is still a little ugliness in our mortgage calculator.  Look at main().  There is one statement that is ugly.

int main()
{
double answer;

stateInstructions();
getInput();
answer = computeMonthlyPayment();
cout <<  "\nYour Monthly Payment: " << answer << endl;
sayGoodbye();
}

We don't like to see main micromanaging.  After all, it hired the services of getInput() to gather data from the user, so why should it dirty its hands with the output?  It seems the sayGoodbye() method is a better place to report the results since it is already doing output anyway.  But how do we get the answer into that method? 

Use global variables?  We could, but we hate to use them unless we are forced to.  There is a better way.

We have used global variables and functional return values to pass information back and forth. Now we introduce arguments and formal parameters.

Let's say we want a method that adds two numbers and returns the sum to the client. Instead of using class variables, we can pass the two numbers down to the method through the method call by placing them inside the functional parentheses:

y = adder(3,5);

The values placed inside the parentheses are called arguments to the method, or just arguments. Arguments can be constants, objects or expressions:

y = adder(x,z);
y = adder( x*3-1, 5/z);
y = adder(y,y);

When defining the method, the method header must declare that it is going to accept two arguments, and specify what their types are:

int adder(int a, int b)
{
// definition of adder
}

The a and b are called formal parameters. They are nothing more than local variables used inside the method whose values are obtained from the arguments passed down from the client.

In the method call:

y = adder(3,5);

the value of 3 is passed to the a (equivalent to a=3 inside the method), and 5 to the b.

In the call

y = adder(x,z);

the contents of x are copied into the formal parameter a, and the contents of z are copied into b.

y = adder( x*3-1, 5/z);

In the above, the two expressions are evaluated, and their results are copied into a and b respectively. Here is a double version of adder():

#include <iostream>
using namespace std;

double adder(double a, double b);

int main()
{
double x = 10.2, y = 35.9, z;

z = adder(x,y);
cout << x << " + " << y << " = " << z << endl;
}

// method adder ------------------
double adder(double a, double b)
{
double temp;

temp = a+b;
return temp;
}

Producing:

console screen shot

5B.3.2 Matching Types between Arguments and Parameters

The data type of the arguments must match, or at least be compatible with the type of the formal parameter. If you were to think of the formal parameter as the left hand side (LHS) of an assignment statement, and its incoming argument as the right hand side (RHS), then the compiler will not complain about the method call if it wouldn't complain about that assignment statement. In the following, we consider the last version of double adder(double a, double b) which has double parameters:

int x = 10, y = 35;
double z;

z = adder(x, y);
z = adder('V', '?');

are okay because:

a = x;
b = y;

and

a = 'V';
b = '?';

are acceptable - the implicit "data widening" conversions of C++ kick in. (Can you remember why 'V' and '?' can be widened implicitly to ints or doubles?). But if adder() were defined, instead, to take float arguments:


// prototype, above main (definition somewhere else)
float adder(float a, float b);

then this would generate a compiler error:

// later, inside main:
double x = 10, y = 35;
double z;

z = adder(x, y);

for the same reason that this would:

a = x;

You can't assign a double to a float without explicit type cast.

Before we apply all of this to our mortgage calculator, let's continue talking about parameters and methods.

decorative space capsule