我正在编写一个程序,并且无法弄清楚为什么会出现错误(注意:我已经修复了它,我很好奇为什么错误在那里以及包含.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 - 我很抱歉这篇文章有多么混乱。如果有什么我可以清理的,请告诉我。
答案 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)
以下是一些想法:
static
。如果您正在使用gcc(您没有说明您正在使用的编译器),则可以使用-E
开关查看预处理器输出。这包括扩展所有#define
并包括所有#include
。
每次展开某些内容时,它会告诉您它所在的文件和行。使用此功能,您可以看到thisFunction()
的定义位置。
答案 5 :(得分:0)
构建的2个不同阶段有2个不同的错误。
在你有重复的第一种情况下,编译器很高兴,但LINKER抱怨,因为当它收集不同源文件中的所有函数定义时,它的注释2被命名为相同。当其他答案陈述时,您可以使用static关键字或使用通用定义。
在第二种情况下,您看到您的函数未在此范围内声明,因为COMPILER抱怨,因为每个文件都需要知道它可以使用哪些函数。
编译在链接之前发生,因此编译器无法提前知道LINKER是否会找到匹配的函数,这就是为什么你使用声明通知COMPILER稍后LINKER会找到定义。
正如您所看到的,您的2个错误并不矛盾,它们是构建中具有特定顺序的2个独立进程的结果。