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

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

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 ++ - >高级 - >显示包括。如果打开这个选项,你会看到在输出窗口中以下内容:

Circular includes

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.ne

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/hffyfdt/article/details/84021471