如何避免涉及全局变量的循环#include?

时间:2017-10-18 21:05:22

标签: c++ global-variables header-files

我有一个标题myglobal.h,它声明了两个全局对象:

#include "log.h"  // defines Clog
Clog log_file;

#include "lib.h"
Clib main_lib;

但是,我的lib.h也使用全局标题:

#include "myglobal.h"  // error: circular #include

class Clib
{
  void func(void) { log_file << "hello"; }
}

如何编写这些标头以避免#include循环?

3 个答案:

答案 0 :(得分:1)

在标题文件中添加extern

// myglobal.h
#include "log.h"
extern Clog log_file;

// #include "lib.h"  DO NOT include this one
extern Clib main_lib;

然后在cpp文件(log.cpp)中定义它

 #include "log.h"
 Clog log_file;

move clib的定义也是一个cpp文件(例如lib.cpp)。

 #include "myglobal.h"

 void Clib::func(void) { log_file << "hello"; }

如果无法将定义移出头文件,则只需要一个cpp文件来定义Clib main_lib。除此之外,只要你有所有标题包含警卫就应该没问题。

答案 1 :(得分:0)

你的通告#include的根本问题是循环思考。特别是,全局标题的概念既定义又取决于您的库。

您可以通过而不是解决此问题,具体取决于您的库实现中的myglobal.h。一种简单的方法是将CLib::func移至lib.cpp

答案 2 :(得分:0)

首先,正如CS Pei的回答所述,请注意您需要包含警卫,并且头文件中的变量声明需要extern(以及源文件中的单独定义)。在C ++ 17中,您可以use inline instead并让链接器对其进行排序。

同时,根据您的使用情况,有一些策略可供选择。

转发声明Clib

myglobal.h仅声明Clib,而不是定义它:

#include "log.h"
extern Clog log_file;

class Clib;
extern Clib main_lib;

然后#include d lib.h d #include"myglobal.h"没有问题。但是,main_lib单独的客户无法使用 log_file,因为其类型不完整。

Clib放在自己的标题

由于Clog不仅取决于log_file,还取决于globallog.h,因此它显然处于更高级别的界面。通过创建#include "log.h" extern Clog log_file;

来形式化
lib.h

然后#include "globallog.h" class Clib { void func(void) { log_file << "hello"; } } 可以包含没有循环的内容:

myglobal.h

最后,main_lib包括#include "globallog.h" // optional: clarifies that log_file is made available #include "lib.h" extern Clib main_lib; 并添加main_lib

lib.h

使用类

声明全局对象

lib.h

中声明myglobal.h

如果没有文件想要Clib没有(您当前的)main_lib(可能是因为main_lib使用的只有lib.h),您只需移动{#include "myglobal.h" // only log_file now class Clib { void func(void) { log_file << "hello"; } } extern Clib main_lib; 的声明即可1}}进入log_file

log_file

请注意,这是之前“log_file在其自己的标头”策略中的变体,其中log.h是现有标头中唯一的 left

log.h

中声明log_file

对称地,如果没有文件想要myglobal.h而不使用main_lib,请在那里声明它并让#include "lib.h" extern Clib main_lib; 只留下lib.h

#include "log.h"

class Clib
{
  void func(void) { log_file << "hello"; }
}

然后public class AlertVm { public int EmailCount { set; get; } public int NotificationCount { set; get; } } 只是

[ChildActionOnly]
public ActionResult Alerts()
{
    var vm = new AlertVm {EmailCount = 4, NotificationCount = 2};
    return PartialView(vm);
}