出于好奇,我想知道是否有办法实现这一目标。
在C ++中,我们知道应该避免使用宏。但是当我们使用包含警卫时,我们确实使用至少一个宏。所以我想知道是否有办法编写一个无宏程序。
答案 0 :(得分:3)
这绝对是可能的,尽管没有包含警卫是不可思议的不良做法。了解#include语句实际执行的操作非常重要:在编译之前,另一个文件的内容会直接粘贴到源文件中。包含防护可以防止再次粘贴相同的代码。
如果在包含该文件的位置键入该文件的内容不正确,则只包含文件会导致错误。例如,您可以在单个编译单元中多次声明(注意:声明,而不是定义)相同的函数(或类)。如果头文件仅包含声明,则无需指定包含保护。
<强> IncludedFile.h 强>
class SomeClassSomewhere;
void SomeExternalFunction(int x, char y);
<强> Main.cpp的强>
#include "IncludedFile.h"
#include "IncludedFile.h"
#include "IncludedFile.h"
int main(int argc, char **argv)
{
return 0;
}
虽然多次声明一个函数(或类)很好,但是定义相同的函数(或类)不止一次是不可能的。如果函数有两个或多个定义,则链接器不知道选择哪个定义并放弃“多重定义的符号”错误。
在C ++中,头文件包含类定义很常见。 include guard会阻止#included文件再次粘贴到源文件中,这意味着您的定义只会在编译的代码中出现一次,并且链接器不会混淆。
不要试图找出何时需要使用它们,而不是在不使用时,只需使用包含警戒。大多数时候避免使用宏是一个好主意;这是一种不邪恶的情况,在这里使用它们并不危险。
答案 1 :(得分:1)
如果确保同一个头文件未多次包含在同一个翻译单元中,则可以这样做。
另外,您可以使用:
#pragma once
如果您不关心可移植性。
但是,您应该避免使用 #pragma once 而不是 Include Guards ,因为:
答案 2 :(得分:1)
简而言之,是的,即使没有pragma。仅当您可以保证每个头文件仅包含一次时。但是,考虑到代码趋于增长,随着头文件数量的增加,保证这种保证变得越来越困难。这就是为什么不使用标题保护被认为是不好的做法。
预处理器宏不赞成,是的。但是,标题包括守卫是一个必要的邪恶,因为替代方案是如此糟糕(#pragma曾经只有你的编译器支持它,所以你失去了可移植性)
关于预处理器宏,请使用以下规则: 如果你能想出一个不涉及宏的优雅解决方案,那就避免它们。
答案 3 :(得分:1)
这绝对可行,我使用了一些早期的C ++库,这些库遵循C的已经误导的方法,基本上要求标题的用户在此之前包含某些其他标题。这是基于彻底了解什么创建了依赖于什么,并尽可能使用声明而不是定义:
enum
只能被定义;在C ++ 2011中,也可以声明{{1} } S)。尽管这种方法有一些优点,但它也有一些严重的缺点。主要优点是它可以实现非常彻底的分离和依赖管理。另一方面,过度侵略性分离,例如使用pimpl-idiom来处理所有事情也会对性能产生负面影响。最大的缺点是许多实现细节对于标头的用户是隐式可见的,因为需要首先明确地包括这个依赖的相应标头。至少,编译器强制您正确获得包含文件的顺序。
从可用性和依赖性的角度来看,我认为普遍的共识是标题最好是自包含的,并且使用包含警卫是较小的邪恶。
答案 4 :(得分:0)
非便携式,非标准
#pragma once
为你工作得好吗?就个人而言,我宁愿使用宏来防止重新入侵,但这是你的决定。