在.h文件和.cpp文件中实现内联函数的区别

3
这句话的实际含义是什么?
//Foo.h
struct Foo {
  void bar() {
    //lots of complex statements
  }
};

并且这个

//Foo.h
struct Foo {
  void bar();
};
//Foo.cpp
inline void Foo::bar() {
  //lots of complex statements
}

这两种方法在最终编译的程序中是否有任何差异,还是保证相同的?请就良好的编码实践/经验发表一些意见,并注意"许多复杂语句"。是否存在某些特定情况,这些语句应该放在头文件中?据我所知,大多数boost库都是仅包含头文件 - 他们为什么要这样选择?
2个回答

8
这两种方法在最终编译程序中是否有任何区别,还是保证是相同的? 两者相同。类/结构体内定义的成员函数隐式为inline。然而,在第一个示例中,函数可以在包含此头文件的每个翻译单元中被内联。在第二个示例中,函数只能在定义函数的cpp文件中被内联。这是因为编译器需要在函数调用点看到函数的定义,以尝试使其内联。
回答评论中的问题:
假设你在一个cpp文件A.cpp中将函数定义标记为inline,并尝试从另一个cpp文件B.cpp中调用此函数。你最终会得到一个"undefined external symbol"错误,这是因为在C和C++中,每个翻译单元都是单独编译的,而位于A.cpp中的函数的定义在编译B.cpp时不可用。
如果该函数仅从定义它的A.cpp中调用,则该定义在同一文件中可用,编译器和链接器可以愉快地编译和链接它。

C++03 7.1.2 函数说明符:
第3段:

在类定义内部定义的函数是内联函数。内联说明符不得出现在块作用域函数声明中。


“在编程实践/经验方面,哪个更好选择?类定义用作类的用户界面。这个接口的用户不需要看到函数的实现细节。他们只需要看到如何使用这个接口。将函数定义(正如您所提到的)放在类内部,会向用户提供不必要的细节,从而使他们难以看到他们实际需要看到的内容。最好的方法是:在类定义中声明函数,不使用inline关键字,并将带有inline关键字的函数定义放在类体外。阅读建议:使用在类外定义的内联成员函数,将inline关键字放在类体内的声明旁边、放在类体外的定义旁边,还是两者都放?
据我所知,大多数Boost库都是仅头文件的 - 为什么他们选择这样做呢?
大多数Boost库都是模板库,对于基于模板的库,编译器需要在使用点看到定义,因此模板函数需要是内联的。
好文章阅读:
为什么模板只能在头文件中实现?

“在最终编译的程序中是否存在差异” - 存在差异,头文件中的函数可以在每个翻译单元中进行内联。 - Csq
@Csq:啊,好的,我刚刚注意到第二种情况的定义在cpp文件中..啊,真糟糕。你是对的。 - Alok Save
@Csq和Alok Save:所以问题在于,带有函数定义的头文件的最终程序将比另一个程序更大,因为函数代码将出现在每个翻译单元中,而如果函数定义在.cpp文件中,编译器很可能会忽略内联请求?这是你试图表达的观点吗? - user2015453
@user2015453:编辑了答案以更好地解释。希望有所帮助。 - Alok Save

2

就功能而言,这两者是相等的。然而,后者只能在 Foo.cpp 文件中进行内联。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接