简体   繁体   中英

Setting Default Parameters in C++

I have a little question about how default values are given to function parameters in C++. The problem I faced is probably due to my lack of understanding as to where the parameters are supposed to be declared/defined in the function prototype or the function header, or both? Codes are below with the errors noted:

#include <iostream>

using namespace std;

float volume(float l, float w, float h);

int main() {

    float length;
    float width;
    float height;

    cout << volume() << endl; // Here, with 'volume()' underlined, it says:
    //no matching function for call to 'volume()'

    cout << "Length: ";
    cin >> length;

    cout << "Width: ";
    cin >> width;

    cout << "Height: ";
    cin >> height;

    cout << "Volume = " << volume(length, width, height) << endl;


}

float volume(float l = 1, float w = 1, float h = 1){

        float vol = l * w * h;

    return vol;
}

In another attempt, here's what happened:

#include <iostream>

using namespace std;

float volume(float l = 1, float w = 1, float h = 1);

int main() {

    float length;
    float width;
    float height;

    cout << volume() << endl;

    cout << "Length: ";
    cin >> length;

    cout << "Width: ";
    cin >> width;

    cout << "Height: ";
    cin >> height;

    cout << "Volume = " << volume(length, width, height) << endl;


}

float volume(float l = 1, float w = 1, float h = 1){ //Here, Xcode says that
// that the error is: Redefinition of default argument. < which I believe I understand.

        float vol = l * w * h;

    return vol;
}

In my last attempt, which is the one that worked, I did this:

#include <iostream>

using namespace std;

float volume(float l = 1, float w = 1, float h = 1);

int main() {

    float length;
    float width;
    float height;

    cout << volume() << endl;

    cout << "Length: ";
    cin >> length;

    cout << "Width: ";
    cin >> width;

    cout << "Height: ";
    cin >> height;

    cout << "Volume = " << volume(length, width, height) << endl;


}

float volume(float l, float w, float h){

        float vol = l * w * h;

    return vol;
}

Could someone please explain to me the logic behind why the latter worked while the first two did not? Is there another way that the code would still work in the same way with the parameters specified elsewhere or the default values set in some place else? Are there any conventions or more favored practices in this area?

Adam

C++ and C are parsed top-down. When the compiler interprets a statement, it doesn't know about things it hasn't read yet.

In your first example, you declare a function called "volume", prototyped as taking 3 floats and returning a float. You then try to call a function called "volume" that takes no parameters, which doesn't exist yet (it would be a different function, since C++ supports polymorphism). You later define a function that can take 0, 1, 2, or 3 floats, but it is both too late and has an incompatible prototype to the first.

Your second example intuitively makes sense to be wrong, kind of like defining variables twice, but I don't have any specific information about why it is invalid code when the default values are identical.

Default parameters must be specified in the function prototype, which must occur prior to first usage in order for the compiler to know about it. Typically, you would put the prototypes with their default values in a header file that gets included above the code.

One thing to watch out for when dealing with default parameters from a shared header file, especially if you use it with dynamic libraries: The default values for the parameters are stored with the caller, and not the function being called. That is, if you update the function with new default values and don't rebuild the code calling that function, the old defaults will still be used by the calling code.

Adding to the above answer from Bjarne Stroustrup

A default argument is type checked at the time of the function declaration and evaluated at the time of the call. Default arguments may be provided for trailing arguments only. For example:

int f (int, int =0 , char * =0 ); // ok

int g (int =0 , int =0 , char *); // error

int h (int =0 , int , char * =0 ); // error

A default argument can be repeated in a subsequent declaration in the same scope but not changed. For example:

void f (int x = 7 );

void f (int = 7 ); // ok

void f (int = 8 ); // error: different default arguments

void g () { void f (int x = 9 ); // ok: this declaration hides the outer one }

Declaring a name in a nested scope so that the name hides a declaration of the same name in an outer scope is error prone.

Default values could be defined in function declaration, as you done in your third attempt. This means usually they're appeared in header files, although this is not a rule.

Note that function declarations are scoped. This means that you could have more than one declaration for a function as long as they have different scopes:

void f(int);

int main() {
    f(3); // argument should specified.

    void f(int = 1);
    f(); // calls f(1)
}

void f(int n = 2) {
}

void g() {
    f(); // calls f(2)
}

In your second attempt you put default values on both declaration and definition of the function. This cause the compiler to confused because they are in the same scope.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM