所以前几天,我正在浏览一些旧的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 ++程序员。
答案 0 :(得分:3)
执行此操作会将类的定义带入包含头文件的每个翻译单元。这是一种非常不寻常的范例,可能对您的编码健康造成危害。特别是,如果main.cpp
和foo.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文件,并且编译它可以在整体速度上产生一些大的收益。