C 中同一功能的多个定义



我正在为神经网写一个库。我需要一些必要的功能,因此我将它们分隔在单独的标头文件中。我还提供了定义后卫。我还将标题文件仅在一个文件中包括在一个文件中,但随后链接器声称程序中所有功能都有多个定义。库结构如下:

namespace maya:
     class neuron [neuron.hpp, neuron.cpp]
     class ffnet [ffnet.hpp, ffnet.cpp]
     struct connection [connection.hpp]
     functions [functions.hpp]

函数标头文件是这样写的:

#ifndef FUNCTIONS_HPP
#define FUNCTIONS_HPP
// some functions here
double random_double(){//some code}
#endif

此functions.hpp文件仅包含一个neuron.hpp中的一个,并且由于ffnet取决于神经元,因此我仅在ffnet中包含了一次neuron.hpp。此ffnet.hpp仅包含在main.cpp中。main.cpp是我用于测试库的文件。

此链接器会引发这样的错误:
/usr/bin/ld: /tmp/ccN7ywby.o: in function `maya::random_double()': neuron.cpp:(.text+0x0): multiple definition of maya::random_double()'; /tmp/ccvDr1aG.o:main.cpp:(.text+0x0): first defined here

/usr/bin/ld: /tmp/cc66mBIr.o: in function `maya::random_double()':`` ffnet.cpp:(.text+0x0): multiple definition of `maya::random_double()'; /tmp/ccvDr1aG.o:main.cpp:(.text+0x0): first defined here

我也使用:
编译了我的程序 g++ main.cpp neuron.cpp ffnet.cpp -o net

我不认为这是需要的,但以防万一:
$ uname -a
Linux brightprogrammer 4.19.0-kali3-amd64 #1 SMP Debian 4.19.20-1kali1 (2019-02-14) x86_64 GNU/Linux

您必须在.hpp或.h文件以外的.cpp文件中编写random_double()的代码。或者,如果将代码保存在.hpp文件中,请在double random_double() { //some code }之前添加inline

问题

您的功能定义具有其完整代码,并在标题中包含在几个汇编单元中。这会导致该函数在每个汇编单元(CPP)中定义,这打破了一个定义规则(ODR)。

include guards确保在同一汇编单元中不会发生相同的定义几次(例如,如果将function.hpp包括在neuron.hpp中,并且也直接包含它)。但是在这里,此标头直接或间接包含在main.cppffnet.cppneuron.cpp中,该标题是第一个定义和2个无效的重新定义。

解决方案

您必须更改function.hpp才能仅保留函数声明:

#ifndef FUNCTIONS_HPP
#define FUNCTIONS_HPP
double random_double();  // no body !!
#endif

并将功能体移至单独的function.cpp,必须添加到您的编译器命令中。

这种方法的优点是:

  • 然后,您可以单独编译实用程序功能。每次更改功能主体时,您都不必再重新编译所有CPP。
  • 通过仅在HPP中共享其他模块需要知道的内容,并隐藏实现细节。
  • ,可以改善封装。
  • 可以通过制作功能库来促进重复使用。
  • 其中的内容将较短(在某个遥远的将来,您的代码将演变为具有数千个HPP的大型项目,这可能会使您获得一些时间)

其他备注

不确定它是否适用,但也请注意,将标头纳入名称空间不是一个好主意。

我还建议阅读有关标题的这篇文章。它很旧,但建议仍然非常相关: - )

请注意,类和内联函数的ODR有例外,在这种情况下,多个定义必须是代币的完全相同的序列。

相关内容

  • 没有找到相关文章

最新更新