函数已经在C++中定义了错误

lau*_*ent 13 c++ include linker-errors

我有一个名为"SimpleFunctions.h"的文件定义如下:

#ifndef SIMPLEFUNCTIONS_H
#define SIMPLEFUNCTIONS_H

namespace my_namespace {

double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
float round(float r) { return round((double)r); }

}

#endif // SIMPLEFUNCTIONS_H
Run Code Online (Sandbox Code Playgroud)

此文件以前只包含在一个文件中,并且工作正常.

今天我把它包含在第二个文件中,它不再有效.在链接时,它告诉我该函数已在"firstfile.obj"中定义.

但是,由于我使用包含警卫,我希望这些函数只定义一次,或者我错过了什么?

pep*_*psi 27

默认情况下,这些功能具有外部链接.这意味着每个转换单元都具有称为double round(double r)和float round(float r)的函数,这会在链接时导致名称冲突.

一些可能的解决方案:

  1. 将函数声明为static,这意味着内部链接
  2. 内联函数
  3. 将实现移出标题并进入ac/c ++文件

在这里阅读更多内容: 什么是外部联系和内部联系?

顺便说一句,包括警卫保护单个翻译单元多次包含头文件.这是你在这里看到的另一个问题.

  • 你是对的。这就是为什么您应该避免在标头内部实现函数的原因。 (2认同)

Mar*_*ett 5

使用“内联”

inline double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
inline float round(float r) { return round((double)r); }
Run Code Online (Sandbox Code Playgroud)

编译器不一定会内联代码(尽管对于此简短功能可能如此),但是链接器不再将其视为单独的函数。

注意-包含卫士会阻止同一包含文件在同一源文件(严格来说是“编译单元”)中被多次包含,这不会阻止它被包含在链接在一起的单独源文件中。这就是为什么通常在标头中声明但在ac文件中定义函数的原因