在 C++ 中设置默认参数

Setting Default Parameters in C++

我对 C++ 中如何为函数参数赋予默认值有一个小疑问。我遇到的问题可能是由于我不了解函数原型或函数头或两者中的参数应该 declared/defined 的位置?代码如下,并指出了错误:

#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;
}

在另一次尝试中,发生了以下情况:

#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;
}

在我最后一次成功的尝试中,我这样做了:

#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;
}

有人可以向我解释为什么后者起作用而前两个不起作用背后的逻辑吗?有没有另一种方法可以使代码仍然以与其他地方指定的参数或其他地方设置的默认值相同的方式工作?在这方面是否有任何惯例或更受欢迎的做法?

亚当

C++ 和 C 是自上而下解析的。当编译器解释一条语句时,它不知道它还没有读过的东西。

在您的第一个示例中,您声明了一个名为 "volume" 的函数,其原型采用 3 个浮点数并返回一个浮点数。然后,您尝试调用一个名为 "volume" 的函数,该函数不带参数,该函数尚不存在(这将是一个不同的函数,因为 C++ 支持多态性)。您稍后定义了一个可以采用 0、1、2 或 3 个浮点数的函数,但是为时已晚并且与第一个原型不兼容。

你的第二个例子在直觉上是错误的,有点像定义变量两次,但我没有任何具体信息说明为什么当默认值相同时它是无效代码。

必须在函数原型中指定默认参数,这必须在首次使用之前发生,以便编译器了解它。通常,您会将原型及其默认值放在包含在代码上方的头文件中。

处理共享头文件中的默认参数时要注意的一件事,尤其是当您将它与动态库一起使用时:参数的默认值存储在调用者中,而不是被调用的函数中。也就是说,如果您使用新的默认值更新函数并且不重建调用该函数的代码,则调用代码仍将使用旧的默认值。

添加到 Bjarne Stroustrup

的上述答案

默认参数在函数声明时进行类型检查,并在调用时进行评估。可以仅为尾随参数提供默认参数。例如:

int f (int, int =0 , char * =0 ); // 好的

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

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

默认参数可以在同一范围内的后续声明中重复但不能更改。 例如:

void f (int x = 7);

void f (int = 7); // 好的

void f (int = 8); // 错误:不同的默认参数

void g () { void f (int x = 9 ); // 好的:这个声明隐藏了外面的声明 }

在嵌套作用域中声明名称以便该名称隐藏外部作用域中的同名声明很容易出错。

默认值可以在函数声明中定义,正如您在第三次尝试中所做的那样。这意味着它们通常出现在头文件中,尽管这不是规则。

请注意,函数声明是有范围的。这意味着您可以对一个函数有多个声明,只要它们具有不同的作用域即可:

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)
}

在您的第二次尝试中,您在函数的声明和定义中都设置了默认值。这会导致编译器混淆,因为它们在同一范围内。