C ++中相同函数的多个定义

问题描述 投票:0回答:2

我正在为神经网络编写一个库。我需要一些必要的功能,所以我将它们分开在一个单独的头文件中。我还提供了定义警卫。我还将头文件只包含在一个文件中,但随后链接器声称程序中的所有函数都有多个定义。库结构如下:

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

c++ linux ld one-definition-rule multiple-definition-error
2个回答
0
投票

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


0
投票

The problem

您将函数定义及其完整代码放在包含在多个编译单元中的标题中。这会导致在每个编译单元(cpp)中定义函数,这会打破One Definition Rule (ODR)

包含保护确保在同一编译单元中不会出现相同的定义(例如,如果在function.hpp中包含neuron.hpp并且也直接包含它)。但是这里的头部直接或间接地包含在main.cppffnet.cppneuron.cpp中,这使得第一个定义和2个无效的重新定义。

The solution

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

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

并将函数体移动到单独的function.cpp,必须将其添加到编译器命令中。

这种方法的优点是:

  • 然后,您可以单独编译实用程序功能。每次更改函数体时,您都不必再重新编译所有cpp。
  • 通过在hpp中共享其他模块需要知道的内容并隐藏实现细节来改进封装。
  • 通过建立功能库,可以在各个项目中促进重用。
  • 包含会更短(如果在一个遥远的未来,你的代码会演变成一个拥有数千hpp的大型项目,这可能会让你获得一些时间)

Additional remarks

不确定它是否适用,但也要注意将标题包含在命名空间中并不是一个好主意。

我也推荐reading this article about headers。它虽然陈旧,但建议仍然非常相关:-)

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

© www.soinside.com 2019 - 2024. All rights reserved.