6.5.1. Default Arguments

Some functions have parameters that are given a particular value in most, but not all, calls. In such cases, we can declare that common value as a default argument for the function. Functions with default arguments can be called with or without that argument.

For example, we might use a string to represent the contents of a window. By default, we might want the window to have a particular height, width, and background character. However, we might also want to allow users to pass values other than the defaults. To accommodate both default and specified values we would declare our function to define the window as follows:

typedef string::size_type sz;  // typedef see § 2.5.1 (p. 67)
string screen(sz ht = 24, sz wid= 80, char backgrnd = ' '),

Here we’ve provided a default for each parameter. A default argument is specified as an initializer for a 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.

Calling Functions with Default Arguments

If we want to use the default argument, we omit that argument when we call the function. Because screen provides defaults for all of its parameters, we can call screen with zero, one, two, or three arguments:

string window;
window = screen();  // equivalent to screen(24,80,' ')
window = screen(66);// equivalent to screen(66,80,' ')
window = screen(66, 256);      // screen(66,256,' ')
window = screen(66, 256, '#'), // screen(66,256,'#')

Arguments in the call are resolved by position. The default arguments are used for the trailing (right-most) arguments of a call. For example, to override the default for backgrnd, we must also supply arguments for ht and wid:

window = screen(, , '?'), // error: can omit only trailing arguments
window = screen('?'),     // calls screen('?',80,' ')

Note that the second call, which passes a single character value, is legal. Although legal, it is unlikely to be what was intended. The call is legal because '?' is a char, and a char can be converted (§ 4.11.1, p. 160) to the type of the left-most parameter. That parameter is string::size_type, which is an unsigned integral type. In this call, the char argument is implicitly converted to string::size_type, and is passed as the argument to height. On our machine, '?' has the hexadecimal value 0x3F, which is decimal 63. Thus, this call passes 63 to the height parameter.

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 Declarations

Although it is normal practice to declare a function once inside a header, it is legal to redeclare a function multiple times. However, each parameter can have its default specified only once in a given scope. Thus, any subsequent declaration can add a default only for a parameter that has not previously had a default specified. As usual, defaults can be specified only if all parameters to the right already have defaults. For example, given

// no default for the height or width parameters
string screen(sz, sz, char = ' '),

we cannot change an already declared default value:

string screen(sz, sz, char = '*'), // error: redeclaration

but we can add a default argument as follows:

string screen(sz = 24, sz = 80, char);  // ok: adds default arguments


Image Best Practices

Default arguments ordinarily should be specified with the function declaration in an appropriate header.


Default Argument Initializers

Local variables may not be used as a default argument. Excepting that restriction, a default argument can be any expression that has a type that is convertible to the type of the parameter:

// the declarations of wd, def, and ht must appear outside a function
sz wd = 80;

char def = ' ';
sz ht();
string screen(sz = ht(), sz = wd, char = def);
string window = screen(); // calls screen(ht(), 80, ' ')

Names used as default arguments are resolved in the scope of the function declaration. The value that those names represent is evaluated at the time of the call:

void f2()
{
    def =   '*';   // changes the value of a default argument
    sz wd = 100; // hides the outer definition of wd but does not change the default
    window = screen(); // calls screen(ht(), 80, '*')
}

Inside f2, we changed the value of def. The call to screen passes this updated value. Our function also declared a local variable that hides the outer wd. However, the local named wd is unrelated to the default argument passed to screen.


Exercises Section 6.5.1

Exercise 6.40: Which, if either, of the following declarations are errors? Why?

(a) int ff(int a, int b = 0, int c = 0);

(b) char *init(int ht = 24, int wd, char bckgrnd);

Exercise 6.41: Which, if any, of the following calls are illegal? Why? Which, if any, are legal but unlikely to match the programmer’s intent? Why?

char *init(int ht, int wd = 80, char bckgrnd = ' '),

(a) init();

(b) init(24,10);

(c) init(14, '*'),

Exercise 6.42: Give the second parameter of make_plural6.3.2, p. 224) a default argument of 's'. Test your program by printing singular and plural versions of the words success and failure.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.124.21