我大致了解它的作用。但我不明白为什么它不是默认设置?在什么情况下需要多次包含某个头文件?
我大致了解它的作用。但我不明白为什么它不是默认设置?在什么情况下需要多次包含某个头文件?
#include
指定其必须表现得完全像用户已经将指定文件的内容复制并粘贴到了#include
行的位置; C ++希望(并且希望)尽可能与C兼容,因此C++从C继承了该行为。// MyContainerImplemention.h
// be sure to #define MYTYPE and MYARRAYSIZE
// before #include-ing this file!
struct ArrayOf##MYTYPE
{
MYTYPE arrayOfItems[MYARRAYSIZE];
};
inline void Set##MYTYPE##Item(struct ArrayOf##MyType * container, int which, MYTYPE item)
{
container[which] = item;
}
[... and so on for various other MYTYPE-specific methods ...]
如果这样做,那么我的 .c 文件可以做类似这样的事情:
#define MYTYPE int
#define MYARRAYSIZE 10
#include "MyContainerImplementation.h"
#undef MYARRAYSIZE
#undef MYTYPE
#define MYTYPE short
#define MYARRAYSIZE 15
#include "MyContainerImplementation.h"
#undef MYARRAYSIZE
#undef MYTYPE
struct ArrayOfint myInts;
struct ArrayOfshort myShorts;
SetintItem(&myInts, 5, 12);
SetshortItem(&myShorts, 3, 2);
[...]
...最终得到每种数据类型的“class”容器及其相关方法的实现,而无需每次手动编写新的容器“class”实现。
是的,这样做非常丑陋 -- 但不如手动编写成千上万行冗余的容器代码那么丑陋。(真正的容器实现头文件实现了一个哈希表,有几百行长)
如果没有包含保护或 #pragma once,编译器将不得不维护一个包含文件列表。这并不容易,因为这些文件有不同的可能路径(而 #pragma once 并不能完全解决这个问题),而原始的 C 编译器需要使用非常有限的内存。
#pragma once
只是迈向拥有适当的C ++模块的一步,因此可以最终消除这种令人烦恼的历史遗留问题。为防止文件被多次包含,需要使用守卫块或者#pragma once
。
#pragma once
虽然在大多数编译器上都受支持,但并非C++标准的正式部分,可能无法在所有编译器上工作。您可以使用守卫块,这将在任何编译器上都能正常工作。在MyClass.hpp
文件中使用守卫块的示例如下:
#ifndef MYCLASS_HPP
#define MYCLASS_HPP
//Code here
#endif
#pragma once
或者包含保护是必要的。 - Silvio Mayolo#ifndef
中使用的标识符需要具有相当程度的唯一性。前几天我们遇到了一个问题,其中一些可怜的人在头文件中使用了类的名称,导致类名被宏替换为空字符串。#define myclass
,然后稍后class myclass { ... };
导致编译器看到了class { ... };
,结果造成了彻底的混乱。 - user4581301