在类体外定义的C ++成员函数的编译

时间:2017-10-03 17:41:36

标签: c++ inline

我有一个像这样的hpp文件:

#ifndef __MYLIB_H
#define __MYLIB_H

class A {
public:
  void func1();
  void func2();  
};

void A::func1() {
  // maybe do something
}

#endif

有一个相应的cpp文件,它具有func2的实现。头文件包含在项目中的其他文件中(更多文件包含这些文件)。当我尝试构建这个时,我会得到多个定义" func1的链接器错误。为什么会这样?由于我使用#ifndef保护了头文件,因此我没想到错误。

如果我将关键字inline添加到func1的定义中,那么一切都很好。因此,如果我不关心内联函数并且我不想在类体中定义,我不能在hpp文件中包含它的定义吗?如果有人能够解释这里发生的事情,那将会非常有帮助。我正在使用GCC 6。

3 个答案:

答案 0 :(得分:2)

问题是您要在每个文件中重新定义func1

#include指令是一个非常简单的命令,它只是将头文件的内容粘贴到指定的位置。

结果是,每次#include标题时,您都会在该文件中“重新定义”func1

答案 1 :(得分:2)

回想一下,整个标题的内容及其可能包含的任何文件,实际上是“复制粘贴”到每个翻译单元 * 中,其中包括在包含点的标题。

这就是为什么在多个CPP文件中包含标题的效果与将字符串复制粘贴到每个CPP中的效果相同,即它与您编写同一成员函数的多个相同定义的效果相同

通过声明函数inline来解决问题,因为C ++允许内联函数的多个定义,只要它们彼此相同即可。将函数体移动到类的声明中也有效,因为这些函数会自动被视为inline

* 在此上下文中,“翻译单元”是您的CPP文件的精美名称。

答案 2 :(得分:0)

实现通常包含在关联的.cpp文件中。将它们放在标题中是有问题的。 inline是一个可以解决这个问题的黑客,你可能不想使用它,因为它会在它出现的任何地方标记出代码,导致严重的重复。

请记住,#include非常类似于在该指令出现的代码中粘贴该文件。对于一个函数有多个实现是不正确的,这就是为什么它们在标题之间被分割出来用于签名,所以理解如何正确使用这些函数,以及实际代码的实现。