#ifndef在链接两个目标文件时是否阻止定义函数两次?

时间:2013-04-25 02:33:13

标签: c++ linker object-files

我有两个类实现(.cpp files

他们都需要一个在header(。h)文件中实现的功能。两个.cpp文件都包含.h文件。编译后,两个.cpp文件变为两个.o文件。

链接两个目标文件时,是否定义了两次函数?

可以#ifndef阻止这种情况吗?

我使用了#ifndef,但收到了以下消息,

ld: 1 duplicate symbol for architecture x86_64

2 个答案:

答案 0 :(得分:5)

您必须了解函数声明(具有给定名称和签名的函数存在的语句)和函数定义(确定内容的代码)之间的区别实际上这个功能。)

如果定义标题中的函数,那么该函数将在每个目标文件中定义,当您尝试将它们链接在一起时会发生冲突; #ifndef无法解决此问题。

如果在标头中声明函数并且在源文件中定义它(必须将其编译为对象,并链接),则不会出现此类问题与使用它的对象)。在这种简单的情况下,不需要#ifndef

例如,函数foo可以在foo.h中声明:

int foo(int);

并在foo.cpp中定义:

int foo(int n)
{
  return(n+3);
}

#ifndef宏解决了另一个问题。

答案 1 :(得分:2)

作为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关键字,因此您可以在那里省略它。