multiple default parameters in functions - my solution feels "inelegant"

Hi all,

I've written the following piece of simple enough code that allows the user to enter the length, width and height of a cube. A function is then called to return the volume of the cube. The user can choose to enter "0" for either the width or height and the function will use the defaults from the function prototype.
I know and understand that the defaults must only be declared from the last parameter first then backwards towards the first, but I'm trying to find a simpler solution for when the user wants the width (2nd param) to use the default value but enter the height (3rd/last param) themselves. The following solution works (per the tests in intro comment), using a combination of default params and overloading but I can't help but feel there's a more elegant solution.

Please note that I'm not concerned with improving the the "if..." logic/program flow in main(), just the function usage. Also, I don't want to substitute global constants for the defaults. Oh, and I'm not worried about the output incorrectly stating the wrong width and height when defaults are used, this is just code for my own testing while I relearn c++ after a 12 year hiatus :)

Much appreciate any input!
-mj

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*	Functions --- Defaults and Overloading 
				Defaults to use:64.00 			73.50 	
Tests	Length	 Length			Width	 Width	 	Height	Height 		Result 
1	User	 2.00 			User	77.00		User	65.10 		 10,025.40		F1		vC(cL,cW,cH);
2	User	 2.00 			User	77.00		Default	73.50		 11,319.00		F1		vC(cL,cW);
3	User	 2.00 			Default	64.00		User	65.10		  8,332.80		F2		vC(cL,   cH);
4	User	 2.00 			Default	64.00		Default	73.50		  9,408.00		F1		vC(cL);
*/

#include <iostream>
#include <string>

// function prototype using no name on first, then 2 defaults (defaults only work if parameters after them also have defaults)
float volumeCube (		float, float cWidth=64, float cHeight=73.5);
// overloaded function to deal with  TEST3 - ADDED int PARAM to signal COMPILER to call this overloaded func instead, width now last param
float volumeCube (int,	float cLength, float cHeight,	float cWidth=64);

float textInput (string textPrompt)
{
	cout << endl << textPrompt;
	float textEnteredInFunc;
	cin >> textEnteredInFunc;	
	return textEnteredInFunc;
}

using namespace std;

int main()
{
	float userLength, userWidth, userHeight, userVolume;
	string textPrompt;
	int sigW=1;

	/* USER INPUT */
	userLength=textInput("Length: ");
	userWidth=textInput("Width: ");
	userHeight=textInput("Height: ");			

	// Test1 - User,User,User
	if (userLength != 0 && userWidth !=0 && userHeight !=0)
		userVolume = volumeCube(		userLength, userWidth,	userHeight);	
	
	// Test2 - User,User,Default
	if (userLength !=0 && userWidth !=0 && userHeight==0)
		userVolume = volumeCube(		userLength, userWidth);					
	
	// Test3 - User,Default,User - *** int sigW forces compiler to use overloaded function
	if (userLength !=0 && userWidth ==0 && userHeight!=0)
		userVolume = volumeCube( sigW,		userLength, userHeight);	

	// Test4 - User,Default,Default
	if (userLength !=0 && userWidth ==0 && userHeight==0)
		userVolume = volumeCube(		userLength);							

	// display result
	cout << "Your cube has a length of " << userLength << ", a width of " << userWidth << " and a height of " << userHeight << "." << endl;
	cout << "This results in a volume of " << userVolume << "." << endl << endl;

	return 0;
}

float volumeCube(float cLength, float cWidth, float cHeight)
{
	cout << " vC1 (cl,cW,cH) ";
	float calcVolume = cLength * cWidth * cHeight;
	return calcVolume;
}

float volumeCube(int signalW, float cLength, float cHeight, float cWidth)
{
	cout << " vC2 (overloaded) ";
	float calcVolume = cLength * cWidth * cHeight;
	return calcVolume;
}
Last edited on
Offering this kind of flexibility in a function usually isn't worth it. Either make it so all items have default values, or make it so they have to explicitly specify the vaules they want.

Other possible solutions to this problem are:

1) take the default value out of the parameter list and put it in main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
float defaultLn = 1;
float defaultWd = 64;
float defautHt =73.5;

float userLn, etc;

// get input from user

if(userLn <= 0)
  userLn = defaultLn;
if(userWd <= 0)
  userWd = defaultWd;
if(userHt <= 0)
  userHt = defaultHt;

userVolume = volumeCube( userLn, userWd, userHt );



2) take the default out of the parameter list and put it in the function body. (same idea, but put the if <= 0 check inside volumeCube)
Thanks for the swift response! I'd just been reading up on functions and I guess I hoped to find you could offer the flexibility by calling them with something like: userVolume(userLn, *blank*, userHt) where the missing parameter would be filled by the prototype's default. No worries though, your two suggested methods make perfect sense and I'd already tested the 2nd one successfully.

Cheers!
mj
Topic archived. No new replies allowed.