对此问题有很多类似的答案,例如:
堆栈溢出很可能会说我有一个重复的问题,但是在研究了所有类似的问题后,为什么人们不鼓励使用此代码,我仍然不明白:
#ifndef _FOO
#define _FOO
// my comment that I only have to write once
int some_method()
{
return 1;
}
#endif
将此称为foo.cpp
。为什么在排除foo.h
的情况下做这样的事情是不好的做法?编译时间会慢一些,但是会慢多少?我相信它将慢几毫秒。为什么懒惰是一件坏事(https://stackoverflow.com/a/9253825/637142)。我只想写一些行之有效的文档,等等。
使用此技术时看到的好处是:
我不必写两次评论。如果我决定更改函数的注释,则还必须更改头文件上的注释。
如果更改方法的签名,则还必须在头文件中对其进行更改。
例如,我在Visual Studio上经常使用F12快捷键来定义方法。默认情况下,Visual Studio将转到头文件。我想去实际的实现。对我来说,看到代码加注释比看到注释更好。
我看到的唯一不利的一面是https://stackoverflow.com/a/1001667/637142。但这比写两次所有内容要少。只是其中的几个而已。
我知道我可能错了,我缺少了一些东西。由于我是C#开发人员,因此我很难理解它。我只是不明白为什么会多次包含此文件。是的,它将被多次包含,但是只有第一次会被编译。其他时候它不会被编译正确吗?
答案 0 :(得分:3)
用#ifndef而不是.h包括.cpp被认为是不好的做法吗?
是的,包括.cpp文件被认为是不好的做法。
int some_method() { return 1; }
头文件通常包含在多个翻译单元中。如果将文件包含在多个TU中,则您已在多个TU中定义了some_method
。这违反了“一个定义规则”,您的程序格式不正确。
即使您小指承诺将该文件准确地包含到另一个TU中,也通常会编译.cpp文件-可能会根据构建系统自动进行编译-在这种情况下,foo.cpp文件将是一个TU,而包含文件将是另一个TU TU,您最终会有多个定义。
- 我不必写两次评论。
即使您不包括.cpp文件,也无需两次编写注释。
- 如果更改方法的签名,则还必须在头文件中更改它。
这是可以自动进行的微不足道的更改。
#define _FOO
该标识符保留给语言实现。您应该使用另一个宏作为标题保护。
答案 1 :(得分:3)
永远不要{。{1}} .cpp文件,因为.cpp扩展名告诉人们文件是一个单独编译的翻译单元。没什么技术上的错误,但它会误导其他程序员,并使您的代码混乱且难以维护。
如果将问题中文件的文件扩展名更改为.h或.hpp,则可以将函数的整个定义包含在头文件中,只要您将其标记为#include
。
也就是说,如果您有一个名为“ foo.hpp”的文件,且具有以下内容,那就完全可以了。
inline
在大型项目中,此将的编译速度大大降低了。将全部(或大部分)代码作为一个庞大的编译单元进行编译,比编译200个单独的编译单元所需的时间更少,但是每次在任何地方进行更改时,都需要重新编译所有代码。那就是存在单独的编译单元要解决的问题。如果对代码的一部分进行更改,则要避免重新编译不相关的代码。在大型项目中,这可以节省大量时间。我从事的项目需要一个多小时才能完全重新编译,而每次进行更改时都必须这样做,这确实很痛苦。