【问题标题】:Is it a good practice to define C++ functions inside header files? [duplicate]在头文件中定义 C++ 函数是一种好习惯吗? [复制]
【发布时间】:2014-10-06 02:43:19
【问题描述】:

我想知道将 C++ 常规函数而不是方法(类中的方法)存储在头文件中是否是一种好习惯。

例子:

#ifndef FUNCTIONS_H_INCLUDED
#define FUNCTIONS_H_INCLUDED

int add(int a, int b)
{
   return a + b;
}

#endif

并像这样使用它:

#include <iostream>
#include "Functions.h"

int main(int argc, char* args[])
{
    std::cout << add(5, 8) << std::endl;
    return 1;
}

这是一个好习惯吗? 提前致谢!

【问题讨论】:

  • 不,您将不可避免地违反单一定义规则。
  • 想想如果头文件包含在两个或多个源文件中会发生什么。
  • @chris 为什么?包含警卫不正是为了防止这种情况吗?
  • @DanielDaranas 不,包含防护可防止将同一个头文件多次包含在同一个源文件中。它不能防止包含多个源文件(如果将源文件单独编译到目标文件中,这将如何工作?)另请阅读translation units(以及 OP:您也应该阅读链接)
  • 您必须标记函数inline 以避免违反单一定义规则

标签: c++ function header-files


【解决方案1】:

没有。如果从两个文件中导入相同的头文件,则会重新定义函数。

但是,通常函数是内联的。每个文件都需要它的定义来生成代码,所以人们通常把定义放在头文件中。

使用static也可以,因为静态函数不会从目标文件中导出,这样在链接过程中就不会干扰其他同名函数。

也可以在标头中的 class 中定义成员函数,因为 C++ 标准将它们视为 inline

【讨论】:

  • static 代替 inline 也可以,但原因不同。
  • 谢谢。扩展答案来解释这一点
  • 类成员函数的细节非常重要。 +1
【解决方案2】:

如果你想在多个源文件(或者更确切地说,translation units)中使用一个函数,那么你在头文件中放置一个函数声明(即一个函数原型),并且定义在一个源文件中。

然后在构建时,首先将源文件编译为目标文件,然后将目标文件链接到最终的可执行文件中。


示例代码:

  • 头文件

      #ifndef FUNCTIONS_H_INCLUDED
      #define FUNCTIONS_H_INCLUDED
    
      int add(int a, int b);  // Function prototype, its declaration
    
      #endif
    
  • 第一个源文件

      #include "functions.h"
    
      // Function definition
      int add(int a, int b)
      {
          return a + b;
      }
    
  • 第二个源文件

      #include <iostream>
      #include "functions.h"
    
      int main()
      {
          std::cout << "add(1, 2) = " << add(1, 2) << '\n';
      }
    

如何构建它在很大程度上取决于您的环境。如果您使用的是 IDE(如 Visual Studio、Eclipse、Xcode 等),那么您将所有文件放入项目中的正确位置。

如果您是从命令行构建,例如,Linux 或 OSX,那么您可以:

$ g++ -c file1.cpp
$ g++ -c file2.cpp
$ g++ file1.o file2.o -o my_program

标志-c 告诉编译器生成一个目标文件,并将其命名为与源文件相同的名称,但带有.o 后缀。最后一条命令将两个目标文件链接在一起形成最终的可执行文件,并将其命名为 my_program(这就是 -o 选项的作用,告诉输出文件的名称)。

【讨论】:

  • 非常感谢。 :) 没关系,我正在使用 Code::Blocks
【解决方案3】:

没有。预处理后,每个源文件都会包含头文件。然后,在链接阶段,您最终会遇到多重定义错误,因为您将拥有同一个函数的多个定义。

使用inlinestatic 将消除链接错误。除非您希望函数为inline,否则最好在标头中声明该函数并在单个源文件中定义并链接它。

如果您将函数声明为inline,则源文件中的每个函数调用都将替换为inlined 函数中的代码。所以,没有定义额外的符号。

如果您将函数声明为static,则函数符号将不会从翻译单元中导出。因此,没有重复的符号。

【讨论】:

  • 这是对正在发生的事情的一个很好的解释。
猜你喜欢
  • 1970-01-01
  • 2017-07-15
  • 2016-03-21
  • 2011-08-30
  • 1970-01-01
  • 2022-01-20
  • 2019-11-20
  • 2019-03-11
  • 1970-01-01
相关资源
最近更新 更多