C++ 包含守卫

Posted

技术标签:

【中文标题】C++ 包含守卫【英文标题】:C++ Include guards 【发布时间】:2016-12-08 02:52:50 【问题描述】:

我知道这个问题被问了很多次,但似乎没有答案可以解决这个问题。

我有两个文件。

Main.cpp

#include <irrlicht\irrlicht.h>

#include <vector>
#include <string> 
#include <iostream>

#include "Scene.h"
#include "Camera.h"
#include "Gui.h"

irr::IrrlichtDevice* device;
irr::video::IVideoDriver* driver;

int main() 
 device = irr::createDevice(irr::video::EDT_SOFTWARE, irr::core::dimension2d<irr::u32>(640, 480), 16, false, false, false, 0);

if (!device)
    return 1;

device->setWindowCaption(L"NeoTrap");
driver = device->getVideoDriver();
sceneManager = device->getSceneManager();
GUIEnvironment = device->getGUIEnvironment();

//Testing
Mesh* ground = new Mesh();
//Testing

while (device->run()) 
    driver->beginScene(true, true, irr::video::SColor(255, 120, 102, 136));

    sceneManager->drawAll();
    GUIEnvironment->drawAll();

    driver->endScene();


device->drop();
return 0;

场景.h

#ifndef _SCENE_HEADER_
#define _SCENE_HEADER_

irr::scene::ISceneManager* sceneManager; 

struct Mesh 
public:
Mesh();

private:
;

class Scene 
public:
Scene();

private:

;

#endif

我要做的是在 Scene.h 中声明一个变量并在主函数中定义它。我不确定我是否不理解包含警卫,但我遇到了奇怪的错误:

'irr': 不是类名或命名空间名 语法错误:缺少 ';'前 '*' 缺少类型说明符 - 假定为 int。注意:C++ 不支持 default-int

但是当我将以下行移回 Main.cpp 文件中时

irr::scene::ISceneManager* sceneManager;

程序编译。我什么时候不能在 scene.h 中声明它并从 main 函数中设置值?

【问题讨论】:

irr::scene::ISceneManager 定义在哪个文件中? Scene.h,位于最顶部。 不,那是你声明一个指向那个类型的变量的地方。 type(类或结构)在哪里定义? @Kurieita ISceneManager 类在哪里声明? 哦,它是在Irrlicht/Irrlichy.h中定义的,这是我正在使用的库。 【参考方案1】:

最好不要在头文件中声明变量。它经常以糟糕的方式结束,因为每个包含标题的文件都会创建自己的sceneManager。当链接器出现将程序放在一起时,它可能会找到数十个sceneManagers,它们都声称自己是真正的sceneManager,厌恶地举起双手,并在控制台上到处散布错误消息。

在scene.h中添加

#include <irrlicht\irrlicht.h>

在顶部声明 irrlicht 的所有细节,以便它们在 scene.h 中可用。

然后改变

irr::scene::ISceneManager* sceneManager; 

extern irr::scene::ISceneManager* sceneManager; 

extern 告诉编译器sceneManager 存在并且存储将分配到其他地方。编译器微笑着继续,把真正的sceneManager 的位置留给链接器。

最后放上

irr::scene::ISceneManager* sceneManager; 

在 Main.cpp 中分配存储空间,以便链接器有一个 sceneManager 可供查找。

Documentation on extern

推荐阅读:When to use extern in C++

【讨论】:

非常好的和非常快速的响应。非常感谢你+1。 :)【参考方案2】:

您声明sceneManager 的类型为irr::scene::ISceneManager*,但是当您声明该变量时,irr 命名空间不存在。在声明变量之前,将include 添加到声明该命名空间的头文件中。

之后,您需要在标头中将 sceneManager 声明为 extern,以便包含该标头的每个编译单元都不会创建自己的变量实例。然后因为它是extern,你还需要在main.cpp 中重新声明它(不带extern)。

【讨论】:

以上是关于C++ 包含守卫的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中使用双包含守卫

为啥有些包含守卫具有定义的值?

除了包含保护之外,C++ 的有效用途还包括保护?

Cython:啥类似于 C 包含守卫?

#pragma once 与包含守卫? [复制]

C:外部变量声明并包含守卫[关闭]