[英]Compilation of C++ member functions defined outside the class body
I have a hpp file like this: 我有一个这样的hpp文件:
#ifndef __MYLIB_H
#define __MYLIB_H
class A {
public:
void func1();
void func2();
};
void A::func1() {
// maybe do something
}
#endif
There is a corresponding cpp file which has the implementation of func2. 有一个相应的cpp文件,该文件具有func2的实现。 The header file is included by other files in the project (and those are included by yet more files).
头文件包含在项目中的其他文件中(而头文件包含在更多文件中)。 When I try to build this, I get "multiple definition" linker errors for
func1
. 当我尝试构建它时,我收到
func1
“多个定义”链接器错误。 Why should that happen? 为什么会这样? Since I've protected the header file with the
#ifndef
, I did not expect the error. 由于我已经使用
#ifndef
保护了头文件,所以我没想到会出现该错误。
If I add the keyword inline
to the definition of func1
, then everything is fine. 如果我将关键字
inline
添加到func1
的定义中,那么一切都很好。 So if I don't care about a function being inlined and I don't want to have the definition in the class body, I cannot include the definition it in the hpp file? 因此,如果我不关心要内联的函数并且不想在类主体中包含定义,则无法在hpp文件中包含该定义? If someone can explain the what's going on here, it'll be very helpful.
如果有人可以解释这里发生的事情,那将非常有帮助。 I'm using GCC 6.
我正在使用GCC 6。
The problem is that you are redefining func1
in every file. 问题是您要在每个文件中重新定义
func1
。
The #include
directive is a very simple command that just pastes the contents of the header file into the location specified. #include
指令是一个非常简单的命令,它仅将头文件的内容粘贴到指定的位置。
The result of this is that each time you #include
your header you are "redefining" func1
in that file. 这样的结果是,每次
#include
您的标头时,您都在该文件中“重新定义” func1
。
Recall that the content of the entire header, along with any files that it may include, is virtually "copy-pasted" into each translation unit * that includes the header at the point of inclusion. 回想一下,整个标头的内容以及它可能包含的任何文件,实际上都是“复制粘贴”到每个包含翻译头中的标头的翻译单元 *中。
That is why the effect of including the header in multiple CPP files is the same as if you literally copy-pasted function definition into each CPP, ie it is the same as if you wrote multiple identical definitions of the same member-function. 这就是为什么将标头包含在多个CPP文件中的效果与您将字面意义上的复制的函数定义逐字复制到每个CPP中的原因相同,即,就像您为同一成员函数编写了多个相同的定义一样。
The problem is solved by declaring the function inline
, because C++ allows multiple definitions of inline functions, as long as they are identical to each other. 通过声明
inline
函数可以解决该问题,因为C ++允许内联函数的多个定义,只要它们彼此相同即可。 Moving the body of the function into the declaration of the class also works, because such functions are automatically considered inline
. 将函数的主体移到类的声明中也是可行的,因为此类函数会自动视为
inline
。
* In this context, "translation unit" is a fancy name for your CPP file. *在这种情况下,“翻译单位”是CPP文件的花哨名称。
Implementations generally go in the associated .cpp
files. 通常,实现在关联的
.cpp
文件中。 Putting them in the headers is problematic. 将它们放在标题中是有问题的。
inline
is a hack to get around this you probably don't want to use since it stamps out that code everywhere it appears, resulting in wild duplication. inline
是一种可以避免这种情况的黑客,您可能不想使用它,因为它会在代码出现的任何地方都将其标记出来,从而导致大量重复。
Remember, #include
is quite like pasting that file in the code right where that directive appears. 请记住,
#include
就像将该文件粘贴到该指令出现的代码中一样。 Having more than one implementation for a function is incorrect, that's why they're split out between header for signature purposes, so it's understood how to use those functions correctly, and implementation for the actual code. 一个函数有多个实现是不正确的,这就是为什么出于签名目的而将它们划分在标头之间的原因,因此可以理解如何正确使用这些函数以及实际代码的实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.