C++ 中头文件中的内联函数

Inline functions in header files in C++

本文关键字:函数 文件 C++      更新时间:2023-10-16

为什么在头文件中定义类的功能是一种不好的做法?

假设我有一个头文件,我在类定义本身中定义了类的函数,如下所示:

头文件.hpp

#ifndef _HEADER_FILE_
#define _HEADER_FILE_
class node{
int i;
public:
int nextn(){
......
return i;
}
}
#endif //_HEADER_FILE_

因此,像这样在类中定义函数会使函数"内联"。因此,如果我们将此头文件包含在两个.cpp文件中,是否会导致"多重定义错误"?在类定义中定义这样的函数是一种不好的做法吗?

由于以下原因,这是一种不好的做法: 如果您需要更改代码,假设在一个简单的 setter 中添加跟踪(它们通常在 .h 中(; 然后,您将需要重新编译 #includes 更改(以及任何依赖项(的所有 CPP 文件。在我目前的项目中,可能会损失长达 1 小时。如果你以后需要添加另一个跟踪,然后另一个等等,你很快就会失去1-2天或等待编译器的工作。

如果您将代码放在 CPP 中,则只需重新链接,这只需要几分钟。你的项目今天可能很小,但几年后谁知道呢。这只是一个好习惯。

另一个(不太好(的原因是,如果你在代码库中搜索字符串"::MyFonction",你不会在声明中找到它,因为没有"::"(我们只想要实现(。但是一个好的IDE无论如何都应该使用上下文搜索而不是字符串搜索来找到它。

这不是一个糟糕的做法(事实上这是司空见惯的(,它不会导致多个定义错误。内联函数从不会导致多个定义错误,这是内联的含义之一。

原型(即类的声明、其功能、其类型(与实现分开的约定来自设计和性能的角度。

  • 类型检查和编译您的家属更便宜。使用你的类的东西可以在不知道你的实现的情况下安全地编译。

  • 每次编译这些依赖项时,编译器都不需要多次解析和重新编译相同的信息。

问题是要记住你用C++在文件的顶部写#include的真正含义:它的意思是"获取其他文件的所有内容,并将它们放在这里"。因此,如果你在代码库中的很多地方使用一个类,那么它每次都会被解析,并在该编译单元的上下文中重新编译。

这正是你必须将模板类

的实现内联在头文件中的原因;编译器需要为每个不同的模板实例化重新解析和编译类(因为这就是模板的意义所在(。

要直接回答您的问题:* 不会,您不会收到多重定义错误。*也许,有些人会从设计的角度考虑它(其他人不会(* 您可能会看到性能差异(尽管不一定是降级,因为我相信 - 尽管我可能是错的(,尽管有上述情况,编译仅标头库仍然可以更快。

如果您的实现很长,该类在代码库中经常使用,并且会经常更改,则可能避免这样做。

为了进一步阅读,可能值得检查"预编译头"。

在 hpp 文件中定义(内联(函数是合法的。请注意,有些人更喜欢在像"inl.hpp"这样的专用扩展名下聚集,但这只是一个样式偏好。