我有两个类实现(.cpp files
)
他们都需要一个在header
(.h) 文件中实现的函数。这两个 .cpp 文件都包含 .h 文件。编译后,这两个.cpp
文件就变成了两个.o
文件。
链接两个目标文件时是否定义了两次函数?
能#ifndef
防止这种情况吗?
我用过#ifndef
,但收到以下消息,
ld: 1 duplicate symbol for architecture x86_64
我有两个类实现(.cpp files
)
他们都需要一个在header
(.h) 文件中实现的函数。这两个 .cpp 文件都包含 .h 文件。编译后,这两个.cpp
文件就变成了两个.o
文件。
链接两个目标文件时是否定义了两次函数?
能#ifndef
防止这种情况吗?
我用过#ifndef
,但收到以下消息,
ld: 1 duplicate symbol for architecture x86_64
您必须了解函数声明(具有给定名称和签名的函数存在的声明)和函数定义(确定函数实际执行的代码)之间的区别。
如果你在头文件中定义函数,那么函数将在每个目标文件中定义,当你尝试将它们链接在一起时会发生冲突;#ifndef
不会解决这个问题。
如果你在头文件中声明函数,并在源文件中定义它(必须编译成对象,并与使用它的对象链接),就不会有这样的问题。在这种简单的情况下,#ifndef
不需要。
例如,函数foo
可以声明在foo.h
:
int foo(int);
并定义在foo.cpp
:
int foo(int n)
{
return(n+3);
}
#ifndef
宏解决了一个不同的问题。
作为 Beta 答案的替代方案,您可以使用关键字在头文件中定义一个自由函数,该函数将包含在多个翻译单元中。inline
考虑一下:
// Foo.h
int foo(){return 1;}
// UsesFoo1.cpp
#include "Foo.h"
int usesFoo2(){return foo();}
// UsesFoo2.cpp
#include "Foo.h"
int usesFoo1(){return foo();}
// Main.cpp
#include <iostream>
int usesFoo1();
int usesFoo2();
int main()
{
std::cout << usesFoo1() + usesFoo2() << std::endl;
}
这会产生链接器错误,因为int foo()
它是在两个单独的翻译单元中定义的。但是,如果您在inline
此处添加关键字,则不会产生错误:
// Foo.h
inline int foo(){return 1;}
注意:在类定义中定义的函数隐含了inline
关键字,因此您可以在此处省略它。