在C++,重复申报仍然是一个问题吗?

Is duplication of declarations still a problem in C++?

本文关键字:一个 问题 仍然是 C++      更新时间:2023-10-16

好的,所以我最近了解了编译器的工作原理以及"链接器"是什么。从我观看的教程视频中,我清楚地看到,如果我包含不止一次的声明,可以说:

void Log(const char* message); 

我会得到一个错误,因为我不止一次声明它。但是目前,当我测试它时,我创建了一个包含该特定声明的头文件,并且我已经在我的主编译单元中多次包含它,如下所示:

#include "Log.h"
#include "Log.h"

我已经删除了 #pragma 一次语句,也没有编写标题保护,但我的程序仍然运行良好且没有任何问题。由于这些视频已有 2-3 年的历史,我想也许已经进行了更新,它完全消除了对警卫和编译指示的需求,但我不确定。

你看过的教程是正确的。 除非使用特殊技术,否则您不能对某物有多个定义。

在这种情况下,虽然你没有定义。

void Log(const char* message); 

是一个声明,您可以拥有多个声明。 如果将代码更改为

void Log(const char* message) {}

然后你会有一个函数定义,并且会得到一个错误。

我会得到一个错误,因为我不止一次声明它。

通常允许重新声明,只要不要混合使用相同名称的不同类型的声明即可。以下是完全合法C++,并且一直都是:

void Log(const char* message); 
void Log(const char* message);

您可能对一个定义规则感到困惑,该规则不允许多次定义事物。

我已经删除了 #pragma 一次语句,也没有编写标题保护,但我的程序仍然运行良好且没有任何问题。

如果你的标头没有定义任何内容,那么它不需要标头保护。然而,按照惯例始终保持警惕更简单,这样就不需要跟踪是否有定义。


奖励答案:所有定义也是声明。通常很容易将类和函数的定义与前向声明区分开来:

return_type function_name(argument_list);        // not a definition of function
return_type function_name(argument_list) { ... } // is  a definition of function
class class_name;                                // not a definition of class
class class_name {                               // is  a definition of class
void member_function();                      // not a definition of function
void inline_member_function() { ... };       // is  a definition of function
};
void class_name::member_function() { ... }       // is  a definition of function

区分变量定义有点困难。不确定时请务必检查规则。

这是一个函数前向声明,您只需让编译器知道稍后将定义函数 X。 在某些资源中,您会发现它被编写/说不允许多个声明,但我认为是干净的代码方法,而不是编译器问题。 而你的情况,你只是包括两次声明, 如果在两个不同的头文件中声明函数并将它们都包含在源文件中,则相同。

切尔诺的教程?

我认为视频中非常清楚地表明,您不能对一个函数进行多个定义。您创建的自定义头文件基本上是复制粘贴的代码块,因此如果它们包含同一函数的不同定义或类,则会导致歧义并按预期抛出错误。

编辑:他想表达的观点 - 如果您将这两个相同的函数定义一起写在一个文件中,那么显然它会由于我上面提到的歧义而引发错误,编译器会检测到该错误,因为它仅在单个文件中。

但是,当您将这两个相同的定义放在不同的文件中时,例如自定义创建的标头"log.h",然后当您将它们导入 cpp 文件两次(或者说将它们导入另一个 cpp 文件并像在 Visual Studio 中一样构建解决方案(时,它将引发链接器错误,因为涉及链接器(多个文件 - 其中链接器的工作是将它们链接到组合的可执行文件中(并且它不能选择不同文件中存在的多个定义。因此,在这种情况下,您将获得多个定义/签名错误。(包括杂注抑制警告(

解决此问题的解决方案是使函数静态,以便在内部定义它们或仅为编译它们所针对的文件定义它们。这使得可以在不同的文件中具有同一函数的多个函数定义,而不会发生链接错误。另一种选择是使其内联。这些情况为您提供了多个定义,没有错误,否则会引发错误。