C2572 - 尝试在另一个文件中包含具有默认参数的函数,然后将此文件包含在 main 中时

C2572 - When trying to include a function with a default parameter in another file, and then include this file in main

提问人:X Y 提问时间:12/13/2022 最后编辑:Remy LebeauX Y 更新时间:12/14/2022 访问量:171

问:

我正在尝试用 C++ 构建一个小程序,以学习预处理器指令以及它们的实际工作方式。

该程序由 5 个文件组成:、、、和main.cppfile1.hfile1.cppfile2.hfile2.cpp

在 中,我声明了 1 个具有默认参数和新类型字节的函数:file1.h

typedef unsigned char byte;

byte f1(byte a, byte b = 5);

在 中,我定义了它:file1.cpp

#include "file1.h"

byte f1(byte a, byte b) {

    return a + b;
}

在 中,我声明了第二个函数,该函数使用 ,并且始终将 10 作为第二个参数传递给它:file2.hf1()

#include "file1.h"

byte f2(byte a);

同样,在 中,我定义了它:file2.cpp

#include "file2.h"

byte f2(byte a) {

    return f1(a, 10);
}

最后,这里是主文件:

#include <iostream>
using namespace std;

#include "file1.h"

int main() {

    cout << f1(3) << endl;

    return 0;
}

目前,一切正常,输出简单。8

但是假设我需要在我的主文件中使用该函数,为此我包括 ,所以主文件现在是:f2()file2.h

#include <iostream>
using namespace std;

#include "file1.h"
#include "file2.h"

int main() {

    cout << (int) f1(3) << endl;

    cout << (int) f2(2) << endl;

    return 0;
}

编译器给出以下错误:Error C2572 'f1': redefinition of default argument: parameter 1

由于包含在 中,现在被重新声明,参数也设置为 。file1.hfile2.hf1()file2.hb5

如果我们假设我不能将声明和定义分别移到 和 ,我该如何防止重新定义?f2()file1.hfile1.cpp

注意:我知道我可以使用指令,但我正在尝试在没有它的情况下解决这个问题,因为我正在尝试专业地学习 C++ 指令。#pragma once

C++ 预处理器 默认参数

评论

1赞 Remy Lebeau 12/13/2022
该语句不属于 ,因为 中的任何内容都不依赖于 中声明的内容。该语句应该移到 of 里面,其中的内容(即 的声明 )实际上被使用。#include "file1.h"file2.hfile2.hfile1.hfile2.cppfile1.hf1()
0赞 X Y 12/13/2022
@Remy Lebeau 是的,你的提议解决了我的问题,但我想为忘记引入依赖关系而道歉 to ,因为在我的实际情况中就是这样。我已经编辑了问题,并替换为返回类型。file2.hfile1.hintbyte

答:

1赞 Remy Lebeau 12/13/2022 #1

在所示的代码中,并且正在多次声明 when 和 are both 'd.bytef1()main.cppfile1.hfile2.h#include

根据 C++ 标准,§8.3.6 [dcl.fct.default]/4

[注 2:默认参数不能通过后面的声明重新定义(甚至不能重新定义相同的值)([basic.def.odr])。

这正是这里发生的事情。

注意:我知道我可以使用指令,但我正在尝试在没有它的情况下解决这个问题,因为我正在尝试专业地学习 C++ 指令。#pragma once

使文件具有适当的标头保护(请参阅 #pragma 一次与包含保护?)是避免重新声明的正确且专业的方法,例如:.h

file1.h:

#ifndef File1H
#define File1H

typedef unsigned char byte;

byte f1(byte a, byte b = 5);

#endif

file2.h:

#ifndef File2H
#define File2H

#include "file1.h"

byte f2(byte a);

#endif

在线演示

评论

0赞 X Y 12/13/2022
我同意这一点,但只有一件事,在 中,如果您创建一个非默认参数,它将在没有任何或预处理器指令的情况下正常编译。那么,为什么在默认参数的情况下它需要所有这些,而在正常参数的情况下它什么都不需要呢?f1()b#pragma once
1赞 Remy Lebeau 12/14/2022
@XY因为C++标准不允许在多个声明中使用默认参数。请参阅具有默认参数的 C++ 函数的多个声明的答案
0赞 X Y 12/14/2022
没关系!顺便说一句,这可以解决问题:预处理器指令可以简单地围绕默认参数值使用。int f(int a, int b #ifndef FILE1_H #define FILE1H = 5 #endif);
0赞 Remy Lebeau 12/14/2022
@XY这是一个糟糕的解决方案。一方面,它有一个错别字。另一方面,如果以后实施适当的标头保护,它将完全禁用。file1.h