简体   繁体   English

在C ++中设置默认参数

[英]Setting Default Parameters in C++

I have a little question about how default values are given to function parameters in C++. 我对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. C ++和C是自上而下解析的。 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. 在第一个示例中,您声明一个名为“ volume”的函数,原型为采用3个浮点数并返回一个浮点数。 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). 然后,您尝试调用一个不包含任何参数的名为“ volume”的函数,该函数尚不存在(这将是一个不同的函数,因为C ++支持多态性)。 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. 稍后您定义一个函数,该函数可以采用0、1、2或3个浮点数,但它都为时已晚,并且与第一个原型不兼容。

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 除了以上来自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 ); int f(int,int = 0,char * = 0); // ok // 好

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

int h (int =0 , int , char * =0 ); 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 ); 无效f(int x = 7);

void f (int = 7 ); 无效f(int = 7); // ok // 好

void f (int = 8 ); 无效f(int = 8); // error: different default arguments //错误:不同的默认参数

void g () { void f (int x = 9 ); 无效g(){无效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. 这会导致编译器感到困惑,因为它们属于同一范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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