将函数放在头文件中的经验法则
Rules of thumb for putting functions in header files
最近我开始将越来越多的函数放入头文件中,主要是为了方便。但我担心我可能做得过头了,我的标题充满了包含,我不确定这是否是一个好主意。
将函数移出或移入头文件的经验法则是什么?
如果你想知道,我说的是开发应用程序,而不是库。
编辑:
我想如果我从我的角度概述内联(自然)标头函数与实现函数的优缺点会很有帮助:
专业内联:
- 更干净/简洁。
- 无需重复签名。
- 无需更改任何生成文件即可链接到新文件。
- 即时引入模板参数的能力。
魂斗罗内联:
- 增加编译时间(我不在乎那么多)
- 许多包含在标题中(如果他们使用防护装置,应该不是一个大问题)
据此,将几乎所有函数都放在标头中似乎是一个好主意,我相信这与 STL 和 Boost 正在做的事情非常接近(尽管它们是库,而不是我的代码)。
我最不可违反的规则之一:头文件中只允许内联的函数体。其他任何事情都在链接阶段要求多个定义出现问题。
标题应主要用于声明而不是定义。我对该规则有例外(是灵活类型),但它们都不涉及非内联函数体。
我的经验法则是"除非必须,否则不在标题中"。至于方便,你觉得增加编译时间很方便吗?
有几个明显的技术方面 - 模板和内联函数必须在标题中 - 来自多个翻译单元的标头必须警惕一个定义规则 - 更直率地说,你想要一个血腥的好理由来考虑将一个离线函数实现放在标题中,我想不出我什至被诱惑过的任何时间。
因此,问题归结为:
在标头中内联还是在实现文件中内联?
因素:
- 你
- 说你正在设计应用程序级代码而不是库,所以你(目前)不必担心其他团队依赖于你的代码,也不必担心他们重新编译(而不是仅仅重新链接)的需要,通过保持实现不合时宜来最小化他们重新编译的需求。
- 但是,如果你正在编写有潜力对其他团队有用的优秀代码,那么你可能会发现自己希望将实现保密。
- 内联与外通常表示琐碎数据获取/设置函数的大约数量级开销...如果您有从性能关键代码重复调用的函数,那么您有理由更喜欢内联
- 标头内实现(特别是如果与声明混合在一起)通常会混淆 API,但有时实际上会使代码更加自我记录
- 本地化和删除冗余(组合声明/定义)肯定会消除拼写错误/错误的可能性,并且通常可以提高生产力
底线:如果你发现自己越来越多地这样做,那么它显然对你有用,没有特别的理由认为你会被烧伤。 留意潜在的问题,但不要根据一些假设的和不太可能实现的问题过度设计东西。
一个好的编码标准会告诉你在源(cpp)文件中实现方法和函数。
如果您愿意,可以在标头中实现模板和内联函数。
既然这已被标记为C++
,为什么不将它们分成逻辑class
es?
通常我在头文件中有一个class
声明,它在相应的源文件中定义。
我使用的两个规则是
1) 如果是内联函数
2)如果是模板函数。
首先,模板函数必须放在标题中。
此外,具有空主体的函数(例如默认构造函数或默认但虚拟析构函数)可以放在标头中。
我从不使用inline
因为编译器不能保证这一点。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 挂起和取消挂起一个文件DLL
- 何时返回指针与返回对象的一般经验法则?
- 点云库 (PCL) - 声明点云时何时应使用 ::P tr 的经验法则?
- 是按值抛出和按引用捕获的经验法则
- 并发::并行端口开销和性能命中率(经验法则)
- 新建和删除的经验法则
- 在C++中使用指针或引用作为函数的返回类型是否有经验法则
- 当通过值传递比通过常量引用传递快时的经验法则
- 标准库/模板化容器的常量语义的经验法则
- C++构造函数重载的经验法则
- 当“虚拟”是一个相当大的开销时,有什么经验法则吗
- 避免违反严格混叠规则的最简单的经验法则
- 将函数放在头文件中的经验法则
- 使用 auto&& 和 const auto & 的经验法则