我正在编写神经网络库。我需要一些必要的功能,因此我将它们分隔在单独的头文件中。我还提供了定义防护。我还只将头文件包含在一个文件中,但是链接器还声称该程序中所有功能都有多个定义。 库结构如下:
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
此function.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
答案 0 :(得分:0)
您可以在包含在多个编译单元中的标头中获得函数定义及其完整代码。这将导致在每个编译单元(cpp)中定义函数,这会破坏One Definition Rule (ODR)。
include保护措施可确保同一定义单元中不会多次出现相同的定义(例如,如果您将function.hpp
包含在neuron.hpp
中,并且也直接包含它)。但是在这里,此标头直接或间接包含在main.cpp
,ffnet.cpp
和neuron.cpp
中,这形成了第一个定义和2个无效的重新定义。
您必须更改function.hpp
以仅保留函数声明:
#ifndef FUNCTIONS_HPP
#define FUNCTIONS_HPP
double random_double(); // no body !!
#endif
并将功能主体移至单独的function.cpp
,必须将其添加到编译器命令中。
这种方法的优点是:
不确定是否适用,但也请注意将标头包含在名称空间中并不是一个好主意。
我还建议使用reading this article about headers。虽然很旧,但建议仍然非常有用:-)
请注意,类和内联函数的ODR例外,在这种情况下,多个定义必须完全相同的标记序列。
答案 1 :(得分:0)
您必须在.hpp或.h文件以外的.cpp文件中编写random_double()
的代码。或者,如果您将代码保存在.hpp文件中,请在inline
之前添加double random_double() { //some code }
。