c ++ #include样式差异

时间:2011-06-03 16:23:30

标签: c++ coding-style include

所以前几天,我正在浏览一些旧的C ++书籍,并注意到了一种创建我以前从未见过的C ++类的方法。到目前为止,我所看到的一切都始终使用#include“header.h”并分别编译实现文件。我看到本书作者所做的实际上是在头文件末尾的实现中添加了一个include指令,并从编译中省略了.cpp文件。有人用过这种风格吗?

例如: 我有 main.cpp中 employee.h employee.cpp

//main.cpp
#include <iostream>
#include <stdio.h>
#include <string>
#include "employee.h"
void main()
{/*some code*/}  

//employee.h
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
class employee
{
   public:
   //public members
   private:
   //private members
}
#endif

//employee.cpp
#include "employee.h"
#include <string>
//public member definitions

我会像这样正常编译这个项目:

g++ main.cpp employee.cpp

但是作者的例子是这样的

//main.cpp
#include <iostream>
#include <stdio.h>
#include <string>
#include "employee.h"
void main()
{/*some code*/}  

//employee.h
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
class employee
{
   public:
   //public members
   private:
   //private members
}
#include "employee.cpp"  // <-- the line of code that caught my attention
#endif

//employee.cpp
 #include <string>
//public member definitions

结果代码编译为

g++ main.cpp

这只是一种风格偏好还是有任何实际好处?我认为它不会很好地扩展,但我也不是一个超级熟练的C ++程序员。

5 个答案:

答案 0 :(得分:3)

执行此操作会将类的定义带入包含头文件的每个翻译单元。这是一种非常不寻常的范例,可能对您的编码健康造成危害。特别是,如果main.cppfoo.cpp#include "employee.h",那么employee上的所有方法都会被定义两次,这违反了{{3}并将创建链接器错误。为了解决这些链接器错误,您需要将定义移动到他们自己的翻译单元,或者将它们标记为inline(可能有效也可能无效)。

然而,在某些情况下,这是一个有用的习惯用语。特别是模板,必须在翻译单元中定义。在这种情况下,当您希望在单独的文件中声明和实现以提高可读性时,您可以执行文件结束#include。当我这样做时,我使用一个特殊的文件扩展名.hpp来表示该文件是特殊的,因为它不是自己编译的。有关示例,请参阅One Definition Rule

答案 1 :(得分:3)

这种方法有时在提供模板时使用,相当于在头文件中提供模板和实现,但允许人们在不经过代码的情况下读取模板声明。同样地,如果你提供inline d函数,那么如果你做了同样的事情,这是可以理解的(不会推荐,但可以理解)。

对于其他任何事情,这是一个糟糕的方法。它不仅要求所有翻译单元实际编译所有函数定义,而且还要求您将所有函数声明为inline,或者包含单个翻译的标头,否则会触发链接器错误。 / p>

答案 2 :(得分:2)

这可能不是主流书籍。无论如何,如果我们通过“它编译”的条件定义正确性,那么是的,这是一个风格问题,两种风格都是正确的。

然而,根据与其他编程语言相匹配的标准和设计指南,唯一真正正确的风格是第一个,与翻译单元的单独编译精神相匹配。正如你自己所说,第二种风格不会很好地扩展。

另一点是#include&lt; stdio.h&gt;,这不再是标准了:

#include <cstdio>

答案 3 :(得分:2)

这肯定会奏效,但它有一些缺点:

  • 更长的编译时间 - 通常如果您更改了一个文件,则只需编译该文件,链接器就会将其与其他较旧的编译结果相结合。当所有内容都包含在一个文件中时,一切都需要立即重新编译。
  • 潜在的命名空间冲突 - 现在可以在一个模块中声明的任何符号对所有符号都可见。如果您使用任何宏,这可能是一个大问题。

答案 4 :(得分:0)

这实际上是我在构建系统中看到的一个技巧,每晚构建以加速它们,包括所有cpp文件,并且编译它可以在整体速度上产生一些大的收益。

相关问题