C ++包含一个“.h”文件,功能重复混乱

时间:2011-05-17 07:03:27

标签: c++ function include header-files

我正在编写一个程序,并且无法弄清楚为什么会出现错误(注意:我已经修复了它,我很好奇为什么错误在那里以及包含.h文件的含义)

基本上,我的程序结构如下:

我正在使用的当前文件,我将调用Current.cc(这是Current.h的实现)。

Current.cc包含一个名为CalledByCurrent.h的头文件(其中有一个名为CalledByCurrent.cc的关联实现)。 CalledByCurrent.h包含类定义。

CalledByCurrent.cc中定义了一个名为thisFunction()的非类函数。 thisFunction()未在CalledByCurrent.h中声明,因为它实际上并不是该类的成员函数(只是一个小帮助函数)。在Current.cc中,我需要使用此功能,因此我只是在thisFunction()的顶部重新定义了Current.cc。但是,当我这样做时,我得到一个错误,说该功能是重复的。当myFunction()中甚至没有声明CalledByCurrent.h时,为什么会这样?

因此,我刚刚从Current.cc移除了该功能,现在假设Current.cc可以访问thisFunction()中的CalledByCurrent.cc。但是,当我这样做时,我发现Current.cc不知道我在说什么功能。有没有搞错?然后我将thisFunction()的函数定义复制到我的CalledByCurrent.h文件的顶部,这解决了问题。你能帮我理解这个行为吗?特别是,为什么它会认为有重复,但它不知道如何使用原文?

p.s - 我很抱歉这篇文章有多么混乱。如果有什么我可以清理的,请告诉我。

6 个答案:

答案 0 :(得分:4)

您从链接器获取了多个定义 - 它看到两个具有相同名称和抱怨的函数。例如:

// a.cpp
void f() {}

// b.cpp
void f() {}

然后

g++ a.cpp b.cpp

给出:

C:\Users\neilb\Temp\ccZU9pkv.o:b.cpp:(.text+0x0): multiple definition of `f()'

这样做的方法是将定义只放在一个.cpp文件中,或者将一个或两个函数声明为静态:

// b.cpp
static void f() {}

答案 1 :(得分:3)

您不能拥有两个具有相同名称的全局函数(即使在2个不同的翻译单元中)。为避免出现链接器错误,请将函数定义为static,以便在翻译单元外部不可见。

修改

您可以使用.cpp关键字在其他extern文件中使用该功能。见这个例子:

//Test.cpp

void myfunc()
{

}

//Main.cpp
extern void myfunc();
int main()
{
    myfunc();
}

它会调用myfunc()中定义的test.cpp

答案 2 :(得分:1)

头文件包含机制应该能够容忍重复的头文件包含。

答案 3 :(得分:1)

那是因为无论何时你只是声明一个函数,它都会被考虑在extern(全局)范围内(无论你是否在头文件中声明它)。链接器将具有相同功能签名的多个实现。

如果那些函数是真正的辅助函数,那么将它们声明为;

static void thisFunction();

其他方式,如果您使用的函数与helper相同,只需在公共头文件中声明它,例如:

//CalledByCurrent.h  (is included in both .cc files)
void thisFunction();

在任一.cc文件中实现thisFunction()。这应该可以正确解决问题。

答案 4 :(得分:0)

以下是一些想法:

  • 您没有在头文件中放置header include guard。如果它被包含两次,你可能会遇到这种错误。
  • 函数的原型(在顶部)与其签名100%不匹配。
  • 您将函数的正文放在头文件中。
  • 您在两个不同的源文件中有两个相同签名的函数,但它们未标记为static

如果您正在使用gcc(您没有说明您正在使用的编译器),则可以使用-E开关查看预处理器输出。这包括扩展所有#define并包括所有#include

每次展开某些内容时,它会告诉您它所在的文件和行。使用此功能,您可以看到thisFunction()的定义位置。

答案 5 :(得分:0)

构建的2个不同阶段有2个不同的错误。

在你有重复的第一种情况下,编译器很高兴,但LINKER抱怨,因为当它收集不同源文件中的所有函数定义时,它的注释2被命名为相同。当其他答案陈述时,您可以使用static关键字或使用通用定义。

在第二种情况下,您看到您的函数未在此范围内声明,因为COMPILER抱怨,因为每个文件都需要知道它可以使用哪些函数。

编译在链接之前发生,因此编译器无法提前知道LINKER是否会找到匹配的函数,这就是为什么你使用声明通知COMPILER稍后LINKER会找到定义。

正如您所看到的,您的2个错误并不矛盾,它们是构建中具有特定顺序的2个独立进程的结果。