1

我只是无法理解为什么这不会编译。

我有三个文件:

主文件

#include "expression.h"

int main(int argc, char** argv)
{

    return 0;
}

表达式.h

#ifndef _EXPRESSION_H
#define _EXPRESSION_H

namespace OP
{
  char getSymbol(const unsigned char& o)
  {
    return '-';
  }
};

#endif /* _EXPRESSION_H */

和表达式.cpp

#include "expression.h"

(Ofc 里面还有更多内容,但即使我评论了除了#includeout 之外的所有内容,它也不起作用)

我用它编译

g++ main.cpp expression.cpp -o main.exe

这是我得到的错误:

C:\Users\SCHIER~1\AppData\Local\Temp\ccNPDxb6.o:expression.cpp:(.text+0x0): multiple definition of `OP::getSymbol(unsigned char const&)'
C:\Users\SCHIER~1\AppData\Local\Temp\cc6W7Cpm.o:main.cpp:(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status

问题是,它似乎解析expression.h了两次。如果我只是使用main.cppOR编译它,expression.cpp我不会得到错误。编译器只是忽略我的#ifndef 并继续......

有什么线索吗?

4

1 回答 1

7

问题是,它似乎解析了 expression.h 两次。

当然可以。您将它包含在两个不同的cpp 文件中。每个包含都将标头的内容转储到该翻译单元中,因此您会获得同一函数的两个定义,从而使链接器理所当然地抱怨。这与包含保护无关,它可以防止您在同一个文件中意外包含两次。

但是,您可以在标头中定义函数。只要它被标记为内联。所以这样做:

namespace OP
{
  inline char getSymbol(const unsigned char& o)
  {
    return '-';
  }
}

inline这是一个承诺,所有这些功能都是完全相同的。因此,多个定义实际上被认为是相同的。但是请注意不要违背这个承诺(不要使用任何可以根据包含的位置更改函数体的构造)。

顺便说一句,命名空间不需要以 a 终止;,所以我冒昧地删除了它。

于 2018-05-23T07:42:46.087 回答