7.4. Function DeclarationsJust as variables must be declared before they are used, a function must be declared before it is called. As with a variable definition (Section 2.3.5, p. 52), we can declare a function separately from its definition; a function may be defined only once but may be declared multiple times. A function declaration consists of a return type, the function name, and parameter list. The parameter list must contain the types of the parameters but need not name them. These three elements are referred to as the function prototype. A function prototype describes the interface of the function.
Parameter names in a function declaration are ignored. If a name is given in a declaration, it should serve as a documentation aid: void print(int *array, int size); Function Declarations Go in Header FilesRecall that variables are declared in header files (Section 2.9, p. 67) and defined in source files. For the same reasons, functions should be declared in header files and defined in source files. It may be temptingand would be legalto put a function declaration directly in each source file that uses the function. The problem with this approach is that it is tedious and error-prone. By putting function declarations into header files, we can ensure that all the declarations for a given function agree. If the interface to the function changes, only one declaration must be changed.
Including the header that contains a function's declaration in the same file that defines the function lets the compiler check that the definition and declaration are the same. In particular, if the definition and declaration agree as to parameter list but differ as to return type, the compiler will issue a warning or error message indicating the discrepancy. 7.4.1. Default ArgumentsA default argument is a value that, although not universally applicable, is the argument value that is expected to be used most of the time. When we call the function, we may omit any argument that has a default. The compiler will supply the default value for any argument we omit. A default argument is specified by providing an explicit initializer for the parameter in the parameter list. We may define defaults for one or more parameters. However, if a parameter has a default argument, all the parameters that follow it must also have default arguments. For example, a function to create and initialize a string intended to simulate a window can provide default arguments for the height, width, and background character of the screen: string screenInit(string::size_type height = 24, string::size_type width = 80, char background = ' ' ); A function that provides a default argument for a parameter can be invoked with or without an argument for this parameter. If an argument is provided, it overrides the default argument value; otherwise, the default argument is used. Each of the following calls of screenInit is correct: string screen; screen = screenInit(); // equivalent to screenInit (24,80,' ') screen = screenInit(66); // equivalent to screenInit (66,80,' ') screen = screenInit(66, 256); // screenInit(66,256,' ') screen = screenInit(66, 256, '#'); Arguments to the call are resolved by position, and default arguments are used to substitute for the trailing arguments of a call. If we want to specify an argument for background, we must also supply arguments for height and width: screen = screenInit(, , '?'); // error, can omit only trailing arguments screen = screenInit( '?'); // calls screenInit('?',80,' ') Note that the second call, which passes a single character value, is legal. Although legal, it is unlikely to be what the programmer intended. The call is legal because '?' is a char, and a char can be promoted to the type of the leftmost parameter. That parameter is string::size_type, which is an unsigned integral type. In this call, the char argument is implicitly promoted to string::size_type, and passed as the argument to height.
Part of the work of designing a function with default arguments is ordering the parameters so that those least likely to use a default value appear first and those most likely to use a default appear last. Default Argument InitializersA default argument can be any expression of an appropriate type: string::size_type screenHeight(); string::size_type screenWidth(string::size_type); char screenDefault(char = ' '); string screenInit( string::size_type height = screenHeight(), string::size_type width = screenWidth(screenHeight()), char background = screenDefault()); When the default argument is an expression, and the default is used as the argument, then the expression is evaluated at the time the function is called. For example, screenDefault is called to obtain a value for background every time screenInit is called without a third argument. Constraints on Specifying Default ArgumentsWe can specify default argument(s) in either the function definition or declaration. However, a parameter can have its default argument specified only once in a file. The following is an error: // ff.h int ff(int = 0); // ff.cc #include "ff.h" int ff(int i = 0) { /* ... */ } // error
If a default argument is provided in the parameter list of a function definition, the default argument is available only for function calls in the source file that contains the function definition. |