C ++头文件的十大错误,如何解决这些问题

Top 10 C++ header file mistakes and how to fix them

C++
header files is a rather mundane topic by most standards. Talking about header files is not as interesting as discussing complex search algorithms or debating design patterns . It’s not an academically stimulating subject to teach, so most CS programs do not
emphasize header file design in their courses.

However,
not having the correct header file design decisions can have significant ramifications on your project in terms of increases build times, compilation fiascos, code maintainability issues and plain information leakage. The larges your C++ project is, the more
important this becomes.

Here’s
a short description of the top 10 header file issues that can crop up if you’re not careful and how to avoid them.

C ++头文件是大多数标准相当平凡的话题。说到头文件是不是在讨论复杂的搜索算法或辩论的设计模式一样有趣。这不是一个学术课题刺激教,所以大部分CS程序不强调头文件在设计自己的课程。
但是,没有正确的头文件中的设计决策会对您的项目显著后果在增加方面构建时间,编译惨败,代码的可维护性问题和平原信息泄露。在拉尔您的C ++项目,更重要的这成为。
下面是如果你不小心,以及如何避免它们能突然出现在排名前10位的头文件问题的简短说明。

http://blog.csdn.net/sergeycao/article/details/52537865

Mistake
# 1: Not using “include guards” in a header file. 错误#1:不使用“包控制”在头文件。

When
the preprocessor sees a #include, it replaces the #include with the contents of the specified header. Using a include guard , you can prevent a header file being included multiple times during the compilation process. The most common way to define an include
guard is as follows:

当预处理器会看到一个的#include,它用指定的头的内容的#include。使用包括后卫,可以防止一个头文件在编译过程中被包含多次。以限定包括防护装置的最常见的方式是如下:

//File: Aircraft.h
#ifndef AIRCRAFT_H
#define AIRCRAFT_H
 
\\the entire file
 
#endif

You usually name your #include guard the same as the name of your header file.

There are two main problems that #include guards help solve.

1. It can help prevent danger circular references between header files which can cause weird compilation failures.

Consider the following example where main.cpp includes both Airbus.h and Boeing.h:

你通常命名include防范与您的头文件的名称。
有迹象表明,#包括警卫帮助解决两个主要问题。
1.它可以帮助防止头文件这可能会导致奇怪的编译错误的危险循环引用。
看看下面的例子,其中的main.cpp包括Airbus.h和Boeing.h:

//File: Airbus.h
#include "Boeing.h"
namespace Airbus
{
	class Carrier
	{
		Carrier();
		~Carrier();
	};
}
 
//File: Boeing.h
#include "Airbus.h"
namespace Boeing
{
	class Carrier
	{
		Carrier();
		~Carrier();
	};
}
 
// main.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "Boeing.h"
#include "Airbus.h"
 
int main(){
    return 0;
}

Compiling the code above gives the following error:

1>c:\users\user\documents\visual studio 2015\projects\smartpointers\headerfiles\airbus.h(2): fatal error C1014: too many include files: depth = 1024

If you’re in a large project with hundreds of include files, it might take some digging to find it out. If you’re using VS2015, you’re in luck because there’s an option to show the include order : Right Click the Project -> Properties -> C/C++ -> Advanced -> Show Includes. If you turn this on, you’ll see the following in the output window:

如果你在一个大的项目是数以百计的包含文件,它可能需要一些挖掘找到它。如果你使用VS2015,你很幸运,因为有显示包括订单的选项:右键单击项目 - >属性 - > C / C ++ - >高级 - >显示包括。如果打开这个选项,你会看到在输出窗口中以下内容:

Looking
at this you can easily tell that there’s a circular reference between Boeing.h and Airbus.h. Fortunately, include guards can help fix the problem. The revised piece of code is below.

看着这个你可以很容易地告诉大家,有Boeing.h和Airbus.h之间的循环引用。幸运的是,包括守卫可以帮助解决这个问题。代码修改后的一段如下。

//File: Airbus.h
#ifndef AIRBUS_H
#define AIRBUS_H
 
#include "Boeing.h"
 
namespace Airbus
{
	class Carrier
	{
		Carrier();
		~Carrier();
	};
}
#endif
 
//File: Boeing.h
#ifndef BOEING_H
#define BOEING_H
 
#include "Airbus.h"
namespace Boeing
{
	class Carrier
	{
		Carrier();
		~Carrier();
	};
}
#endif
 
// main.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
#include "Boeing.h"
#include "Airbus.h"
 
int main(){
    return 0;
 
}

2. In the absence of an include guard, a file will need to be processed multiple times and can cause significant build delays in large systems.

2.在没有包括护罩,一个文件将需要多次处理,并可能导致在大型系统显著生成延迟。

Recommendation: Always
use an include guard as shown above to optimize build times and avoid weird build errors. If your compiler supports and optimized #pragma once as an include guard mechanism, you should use that because it is usually more performant and less error prone than
using an explicit include guard. For example, a lot of our internal code uses the following convention for public header files. Notice that if we‘re on a MS compiler where _MSC_VER is defined, we‘ll use the #pragma directive which is supported and optimized
by the compiler.

建议:请始终使用如上图所示,优化生成时间,避免怪异的生成错误的包括后卫。如果你的编译器支持和优化的#pragma一次作为一个include防范机制,你应该使用,因为它通常是更好的性能和更小的误差比使用显式俯卧包括后卫。例如,很多我们的内部代码使用公共头文件下列约定。请注意,如果我们在哪里_MSC_VER定义一个MS的编译器,我们将使用它支持和编译器优化#pragma指令。

#ifndef HEADER_FILE
#define HEADER_FILE
 
#ifdef _MSC_VER
#pragma once
#endif  // _MSC_VER
 
// Contents of the header file here
 
#endif  // HEADER_FILE
http://blog.csdn.net/sergeycao/article/details/52537865

MISTAKE # 2: Incorporating "using namespace" statements at top level in a header file

错误#2:在头文件顶层纳入“使用命名空间”语句

Headers
should define only the names that are part of the interface, not names used in its own implementation. However, a using directive at top level in a header file injects names into every file that includes the header.

This
can cause multiple issues:

  1. It
    is not possible for a consumer of your header file to undo the namespace include – thus they are forced to live with your namespace using decision, which is undesirable.
  2. It
    dramatically increases the chance of naming collissions that namespaces were meant to solve in the first place.
  3. It
    is possible that a working version of the program will fail to compile when a new version of the library is introduced. This happens if the new version introduces a name that conflicts with a name that the application is using from another library.
  4. The
    “using namespace” part of the code takes effect from the point where it appears in the code that included your header, meaning that any code appearing before that might get treated differently from any code appearing after that point.

头应该定义只有那些接口,在它自己的实现不使用名称的一部分的名字。然而,使用指令在头文件中顶级的名字注入到每个包含头文件。
这可能会导致多种问题:
这是不可能的头文件的消费者撤消命名空间包含 - 因此,他们被迫生活与你的空间使用的决定,这是不可取的。
这大大增加了命名命名空间注定摆在首位,以解决冲突的机会。
可能的是该程序的工作版本将失败时被引入该库的新版本进行编译。如果发生这种情况,新版本引入了与该应用程序是从另一个库使用名称相冲突的名字。
代码中的“使用命名空间”的一部分生效了点地方出现,包括你的头,这意味着在此之前出现的任何代码可能会被从该点后出现的任何代码区别对待的代码。

Recommendations:

1.
Try to avoid putting any using namespace declarations in your header files. If you absolutely need some namespace objects to get your headers to compile, please use the fully qualified names (Eg. std::cout , std::string )in the header files.

1.尽量避免将任何使用空间声明在你的头文件。如果你绝对需要一些空间物品,让您的头编译,请在头文件中使用完全合格的名称(如:性病::法院,性病::字符串)。

//File:MyHeader.h:
class MyClass
{
private:
    Microsoft::WRL::ComPtr<iunknown> _parent;
    Microsoft::WRL::ComPtr<iunknown> _child;
}
</iunknown></iunknown>

2. If recommendation #1 above causes too much code clutter – restrict your “using namespace” usage to within the class or namespace defined in the header file. Another option is using scoped aliases in your header files as shown below.

2.如果建议1以上引起太多的代码混乱 - 限制你的“使用命名空间”的使用在头文件中定义的类或命名空间内。如下图所示另一种选择是在头文件中使用范围的别名。

//File:MyHeader.h:
 
class MyClass
{
namespace wrl = Microsoft::WRL; // note the aliasing here !
private:
    wrl::ComPtr<iunknown> _parent;
    wrl::ComPtr<iunknown> _child;
}
</iunknown></iunknown>
http://blog.csdn.net/sergeycao/article/details/5253

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

原文地址:https://www.cnblogs.com/kwincaq/p/10430239.html

时间: 2024-10-04 12:15:20

C ++头文件的十大错误,如何解决这些问题的相关文章

Spring常犯的十大错误,你踩过吗?

1.错误一:太过关注底层 我们正在解决这个常见错误,是因为 "非我所创" 综合症在软件开发领域很是常见.症状包括经常重写一些常见的代码,很多开发人员都有这种症状. 虽然理解特定库的内部结构及其实现,在很大程度上是好的并且很有必要的(也可以是一个很好的学习过程),但作为软件工程师,不断地处理相同的底层实现细节对个人的开发生涯是有害的. 像 Spring 这种抽象框架的存在是有原因的,它将你从重复地手工劳作中解放出来,并允许你专注于更高层次的细节 -- 领域对象和业务逻辑. 因此,接受抽象

Web设计的十大错误

Web设计的十大错误: 无谓使用不成熟技术.网站不应该靠吹嘘采用最新的web技术来吸引用户,这样可能会吸引一些不用脑子的人,但是主流用户会更关心有用的内容以及站点提供良好客户服务的能力.除非从事因特网产品和服务销售业务,否则最好等到该技术具有一些使用经验之后再采用. 滚动文字.滚动块和不停运行的动画.不要让网页上有不停移动的元素.移动的图像对人类的视觉太过刺激.网页不应该不断地刺激人们的感官,而该让用户安安静静地看文字. 滚动显示的长页面.所有重要的内容和导航选项应该位于页面顶端.在导航页面上减

头文件循环引用的错误

In file included from /usr/include/c++/5/memory:81:0,from Threadpool.h:12,from testThreadpool.cc:7:/usr/include/c++/5/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = wd::Thread]':/usr/include

STM32 关于头文件路径没添加错误问题(cannot open source input file &quot;spi.h&quot;: No such file or directory)

error:  #5: cannot open source input file "spi.h": No such file or directory 1.出现这种问题,首先要确认头文件的命名要与文件名一致,如下: #ifndef _SPI_H #define _SPI_H #endif 2.添加路径,问题即可解决 3.确认OK,编译,问题解决! 原文地址:https://www.cnblogs.com/xingboy/p/9541267.html

GNU Linux 64位系统中fatal error: stdio.h: 没有那个文件或目录的错误的解决方法

在64位系统中,编写一个C语言程序后,使用gcc进行编译时,出现了如下的错误: test.c:1:19: fatal  error: stdio.h: 没有那个文件或目录 #include <stdio.h> 针对以上的情况,对于在32环境下一般不会出现这个问题,因为已经把libc的头文件包括在系统中了,那么针对这样的情况,主要检查是否安装了完备的开发环境: build-essential package - Installs the following collection to compi

Spring常见的十大错误,78%的老程序员都踩过这些坑!

首先我们来看一下,Spring常见错误有那些 太过关注底 内部结构 "泄露" 缺乏关注点分离 缺乏异常处理或处理不当 多线程处理不当 不使用基于注解的验证 (依旧)使用基于xml的配置 忽略 profile 无法接受依赖项注入 缺乏测试,或测试不当 接下来就一一介绍这些常见的错误1. 错误一:太过关注底层我们正在解决这个常见错误,是因为 "非我所创" 综合症在软件开发领域很是常见.症状包括经常重写一些常见的代码,很多开发人员都有这种症状.虽然理解特定库的内部结构及其

数据挖掘中易犯的十大错误

按照Elder博士的总结,这10大易犯错误包括: 0. 缺乏数据(Lack Data)1. 太关注训练(Focus on Training)2. 只依赖一项技术(Rely on One Technique)3. 提错了问题(Ask the Wrong Question)4. 只靠数据来说话(Listen (only) to the Data)5. 使用了未来的信息(Accept Leaks from the Future)6. 抛弃了不该忽略的案例(Discount Pesky Cases)7.

2016第51周五产品经理的十大错误

错误1: 将用户需求混淆为产品需求 大部分产品经理的工作流程是:收集完用户需求,开始编写产品需求文档,然后交给技术人员开发,接下来跟踪项目进度,协调资源,验收成果,最后发布产品. 整个流程没有错,容易产生错误的地方在于,产品需求如何确定.在淘宝内部的产品经理也是如此,经常把运营同学的需求直接翻译成文档,交给技术人员开发.最后的结果是产品的功能点越来越多,产品越来越复杂,成为一个大杂烩. 一定要从产品设计的角度思考需求,把用户的需求转化成为产品需求.在火车没有出现的时候,你问用户最想要什么?用户会

Java程序员容易犯的常见十大错误转)

1. Array 转 ArrayList 一般开发者喜欢用: List<String> list = Arrays.asList(arr); Arrays.asList() 会返回一个ArrayList,这是Arrays里内嵌的一个私有静态类,而并不是java.util.ArrayList类 java.util.Arrays.ArrayList 有set(), get(), contains()方法,但并支持添加元素,所以大小是固定的,想要创建一个真正的ArrayList,你应该: Array