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

时间:2013-09-28 07:59:58

标签: c++ function header multiple-definition-error

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

假设我有一个头文件,我在类定义本身中定义了类的功能,如

headerfile.hpp

#ifndef _HEADER_FILE_
#define _HEADER_FILE_

class node{
int i;

public:
int nextn(){
......
return i;
}
}

#endif //_HEADER_FILE_

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

5 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:2)

实践并不坏(事实上它很常见)并且它不会导致多个定义错误。内联函数永远不会导致多个定义错误,这是内联的意义之一。

答案 2 :(得分:1)

从实现中分离原型(即,类的声明,函数,类型)的约定来自设计和性能观点。

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

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

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

这正是您必须在头文件中嵌入模板类的实现的原因;编译器需要为每个不同的模板实例化重新解析和编译类(因为那是什么模板)。

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

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

为了进一步阅读,可能需要检查"预编译的标题。"

答案 3 :(得分:0)

在hpp文件中定义(内联)函数是合法的。请注意,有些人喜欢在“inl.hpp”这样的专用扩展下收集,但这只是一种风格偏好。

答案 4 :(得分:0)

当您编写模板类/方法时,这并不是一种不好的做法。

inline方法可以帮助您遵守一个定义规则。

对于模板类,头文件中应该inline个方法(也可以显式实例化它们以避免inline - )。

关于inline方法的坏处是,在修改每个inline -ed方法后,所有使用该方法的单元都必须重新编译,但是如果你在{{1}中移动它们文件编译器可以创建一个目标文件,并将其重用于许多翻译单元。

因此,由您决定是否.cpp您的实施(如果可能的话)。