Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

Chapter 6: Creating Functions

87

This is the same FunctionDemo() program, except that SquareDemo() accumulates the square of the values entered. The function square() returns the value of its one argument multiplied by itself. The change to the sumSequence() function is simple — rather than accumulate the value entered, the function now accumulates the result returned from square().

Functions with multiple arguments

Functions may have multiple arguments that are separated by commas. Thus, the following function returns the product of its two arguments:

int product(int arg1, int arg2)

{

return arg1 * arg2;

}

main() exposed

The “keyword” main() from our standard program template is nothing more than a function — albeit a function with strange arguments — but a function nonetheless.

When a program is built, C++ adds some boilerplate code that executes before your program ever starts (you can’t see this code without digging into the bowels of the C++ library functions). This code sets up the environment in which your program operates. For example, this boilerplate code opens the default input and output channels cin and cout.

After the environment has been established, the C++ boilerplate code calls the function main(), thereby beginning execution of your code. When your program finishes, it exits from main(). This enables the C++ boilerplate to clean up a few things before turning control over to the operating system that kills the program.

Overloading Function Names

C++ allows the programmer to assign the same name to two or more functions. This multiple use of names is known as overloading functions.

In general, two functions in a single program cannot share the same name. If they did, C++ would have no way to distinguish them. Note, however, that the name of the function includes the number and type of its arguments — but does not include its return argument. Thus the following are not the same functions:

88 Part II: Becoming a Functional C++ Programmer

void someFunction(void)

{

// ....perform some function

}

void someFunction(int n)

{

// ...perform some different function

}

void someFunction(double d)

{

// ...perform some very different function

}

void someFunction(int n1, int n2)

{

// ....do something different yet

}

C++ still knows that the functions someFunction(void), someFunction(int), someFunction(double), and someFunction(int, int) are not the same. Like so many things that deal with computers, this has an analogy in the human world.

void as an argument type is optional. sumFunction(void) and sumFunction() are the same function. A function has a shorthand name, such as someFunction(), in same way that I have the shorthand name Stephen (actually, my nickname is Randy, but work with me on this one). If there aren’t any other Stephens around, people can talk about Stephen behind his back. If, however, there are other Stephens, no matter how hand­ some they might be, people have to use their full names — in my case, Stephen Davis. As long as we use the entire name, no one gets confused — however many Stephens might be milling around. Similarly, the full name for one of the someFunctions() is someFunction(int). As long as this full name is unique, no confusion occurs.

The analogies between the computer world (wherever that is) and the human world are hardly surprising because humans build computers. (I wonder . . .

if dogs had built computers, would the standard unit of memory be a gnaw instead of a byte? Would requests group in packs instead of queues?)

Here’s a typical application that uses overloaded functions with unique full names:

int intVariable1, intVariable2; // equivalent to // int Variable1; // int Variable2;

double doubleVariable;

//functions are distinguished by the type of

//the argument passed

 

 

 

Chapter 6: Creating Functions

89

 

 

 

 

 

 

 

 

someFunction();

// calls someFunction(void)

 

 

 

someFunction(intVariable1);

// calls someFunction(int)

 

 

 

someFunction(doubleVariable); // calls someFunction(double)

 

 

 

someFunction(intVariable1, intVariable2); // calls

 

 

 

 

// someFunction(int, int)

 

 

 

// this works for constants as well

 

 

 

someFunction(1);

// calls someFunction(int)

 

 

 

someFunction(1.0);

// calls someFunction(double)

 

 

 

someFunction(1, 2);

// calls someFunction(int, int)

 

 

In each case, the type of the arguments matches the full name of the three functions.

The return type is not part of the extended name (which is also known as the function signature) of the function. The following two functions have the same name — so they can’t be part of the same program:

int someFunction(int n);

//

full name of the function

 

//

is someFunction(int)

double someFunction(int n); //

same name

You’re allowed to mix variable types as long as the source variable type is more restrictive than the target type. Thus an int can be promoted to a double. The following is acceptable:

int someFunction(int n);

double d = someFunction(10); // promote returned value

The int returned by someFunction() is promoted into a double. Thus the following would be confusing:

int someFunction(int n); double someFunction(int n);

double d = someFunction(10);// promote returned int?

// or use returned double as is

Here C++ does not know whether to use the value returned from the double version of someFunction() or promote the value returned from int version.

Defining Function Prototypes

The programmer may provide the remainder of a C++ source file, or module, the extended name (the name and functions) during the definition of the function.

90

Part II: Becoming a Functional C++ Programmer

The target functions sumSequence() and square() — appearing earlier in this chapter — are both defined in the code that appears before the actual call. This doesn’t have to be the case: A function may be defined anywhere in the module. (A module is another name for a C++ source file.)

However, something has to tell the calling function the full name of the func­ tion to be called. Consider the following code snippet:

int main(int nNumberofArgs, char* pszArgs[])

{

someFunc(1, 2);

}

int someFunc(double arg1, int arg2)

{

// ...do something

}

main() doesn’t know the full name of the function someFunc() at the time of the call. It may surmise from the arguments that the name is someFunc(int, int) and that its return type is void — but as you can see, this is incorrect.

I know, I know — C++ could be less lazy and look ahead to determine the full name of someFunc()s on its own, but it doesn’t. It’s like my crummy car; it gets me there, and I’ve learned to live with it.

What is needed is some way to inform main() of the full name of someFunc() before it is used. This is handled by what we call a function prototype.

A prototype declaration appears the same as a function with no body. In use, a prototype declaration looks like this:

int someFunc(double, int);

int main(int nNumberofArgs, char* pszArgs[])

{

someFunc(1, 2);

}

int someFunc(double arg1, int arg2)

{

// ...do something

}

The prototype declaration tells the world (at least that part of the world after the declaration) that the extended name for someFunc() is someFunction(double, int). The call in main() now knows to cast the 1 to a double before making the call. In addition, main() knows that the value returned by someFunc() is an int.