6.5. Default Arguments

function, default arguments, argument
Time: 00:05:11 | Download: Large, Large (CC) Small | Streaming, Streaming (CC) | Slides: PDF, PPTX
Review

Computer scientists often face conflicting trade-offs. For example, the classic time-space trade-off: making a program run faster at the expense of using more memory or vice versa. Another trade-off is functional flexibility versus simplicity or ease of use. Imagine a program with a function that creates a window. A flexible function might allow a programmer to specify the window's width and height, its x- and y-coordinates on the screen, and its color. Requiring five values to configure the window makes the function flexible but hard to use, especially if we don't care about the window's location or color. Alternatively, a simple version that only requires the window's size may not give us enough control when creating a complex user interface.

void window(int width, int height){...}
void window(int width, int height, int x, int y, int color){...}
(a)
void window(int width, int height)
{
	window(width, height, 0, 0, 0xFFFFFF);
}
(b)
Overloaded functions: simplicity vs. flexibility. Overloaded functions are one way to maintain flexibility when needed, but they can also provide simplicity when it isn't.
  1. The first function is simple to use: programmers calling it only need to supply the window size (the width and height). The second function is more flexible , allowing programmers greater control over the window.
  2. A simple, easily used function might make some assumptions for often-used values and then call the complex function - chaining the function calls together. The Java API includes many examples of this approach and refers to the simple version as a convenience method.

C++ provides another, more memory-efficient (and, in my opinion, a more elegant) choice: default arguments. A default argument is a value provided for an argument if the function call doesn't furnish one. Programmers specify the default values in the function declaration or prototype, as the next figure illustrates.

(a) void window(int width, int height, int x = 0, int y = 0, int color = 0xFFFFFF) {...}
(b) window(100, 200);
(c) window(100, 200, 50);
(d) window(100, 200, 50, 75);
(e) window(100, 200, 50, 75, BLUE);
Default arguments: simplicity vs. flexibility. The window function provides three default arguments. The function calls must supply values for the first two arguments; they can either accept the defaults for the remaining arguments or supply values for them.
  1. A function definition (recall that a function definition is sometimes a declaration) showing the default arguments (highlighted).
  2. Supplies values for width and height, accepts the defaults for x, y, and color.
  3. Supplies values for width, height, and x, accepts the defaults for y and color.
  4. Supplies values for width, height, x and y, accepts the default for color.
  5. Supplies values for all function arguments.

Default Argument Rules

function, default arguments, function binding, argument, parameter

We must follow four rules when using default arguments. Some may seem confusing, but the following elaborations and examples demonstrate that they are relatively straightforward. If we recall that C++ matches function call arguments to a function's parameters (Figure 2) in English's reading order - left to right - some are even intuitive.

  1. Parameter lists may not have arguments without a default value following (i.e., to the right of) an argument with a default.
  2. Once a function call accepts a default argument, it must accept all following defaults (i.e., function calls can't skip arguments).
  3. If the function definition and declaration are separate, then the default values appear in the declaration (i.e., in the prototype, often written in a header file).
  4. If a program overloads a function with default arguments, all possible function call argument lists must always match exactly one function.
Rules for defining and using functions with default arguments.

 

void function(int a, int b = 1, int c = 2);	// okay
void function(int a, int b = 1, int c);		// error
Rule 1: creating functions. When programmers give a parameter a default value, they must give default values to all the parameters to its right in the parameter list.

 

function(50);		// okay
function(60, 70);	// okay
function(60, 70, 80);	// okay
function(60, , 80);	// error
Rule 2: calling functions. When a function call accepts a default argument, it must accept all default arguments to its right.

 

Prototype (declaration)
library.h
Definition
library.cpp
void function(int a, int b = 1, int c = 2);
void function(int a, int b, int c)
{
	cout << a << " " << b << " " << c << endl;
}
Rule 3: separate prototypes and definitions. Suppose programmers implement a function as a separate prototype (in a header file) and a definition (in a source code file). In that case, they specify the default values in the function prototype.

 

void function();				// version 1
void function(int a, int b = 1, int c = 2);	// version 2
function();		// version 1
function(10);		// version 2
function(10, 20);	// version 2
function(10, 20, 30);	// version 2
(a)(b)
void bad_function(int a);			// version 1
void bad_function(int a, int b = 1, int c = 2);	// version 2
bad_function(10);	// version 1 or 2?
(c)(d)
Rule 4: function calls may not be ambiguous. Function overloading and default arguments are independent but not mutually exclusive constructs. However, when programmers combine them, they may not create an ambiguous function binding: no pattern of function arguments may match more than one overloaded function.
  1. The program defines two versions of function: the first with no parameters, and the second with three parameters, with the last two having default values.
  2. Programs can call the two functions in four distinct ways: version 1 with no arguments and version 2 with one, two, or three. All valid function calls uniquely match only one version.
  3. The two function prototypes violate rule 4: the functions are ambiguous (the example highlights the error).
  4. Demonstrates the problem with (c). The call matches both function versions when the version 2 defaults are accepted. The compiler cannot determine which function to call.

Default Argument Examples And Self-Test

function, default arguments
Function Definition
void function(int a, int b = 1, int c = 2)
{
	cout << a << " " << b << " " << c << endl;
}
function();
function(50);
(a)(b)
function(60, 70);
function(60, 70, 80);
(c)(d)
function(60, , 80);
function(60, 70, 80, 90);
(e)(f)
Calling a function with default arguments. Examine the function definition and calls. Determine the output of each function call.
  1. Hover the mouse pointer here for the answer
  2. Hover the mouse pointer here for the answer
  3. Hover the mouse pointer here for the answer
  4. Hover the mouse pointer here for the answer
  5. Hover the mouse pointer here for the answer
  6. Hover the mouse pointer here for the answer