【问题标题】:#pragma once and #include issues#pragma once 和 #include 问题
【发布时间】:2012-06-06 16:27:08
【问题描述】:

我遇到了循环引用的问题(即 A.h 和 B.h #包括彼此),有些人建议我使用 #pragma 一次来防止这种情况。但是,此解决方案似乎仍然无法正常工作。

发生的情况是 A 类不再在 A.h 以外的任何文件中被识别(甚至在 A.cpp 中也不被识别),B 类也是如此。

让我给你看代码:

啊.h

#pragma once
#include "B.h"

class A {
public: B* b;

};

B.h

#pragma once
#include "A.h"

class B {
    public: A* a;
};

A.cpp

#include "stdafx.h"
#include "A.h"
#include "B.h"

B.cppA.cpp

相同

错误跟踪如下:

1> B.cpp 1>c:\users\user\documents\visual studio 2010\projects\envmodel\test\b.h(5):错误 C2143:语法错误: 失踪 ';'在“”之前 1>c:\users\user\documents\visual studio 2010\projects\envmodel\test\b.h(5):错误 C4430:缺少类型 说明符 - 假定为 int。注意:C++ 不支持默认整数 1>c:\用户\用户\文档\视觉工作室 2010\projects\envmodel\test\b.h(5):错误 C4430:缺少类型 说明符 - 假定为 int。注意:C++ 不支持 default-int 1> A.cpp 1>c:\users\user\documents\visual studio 2010\projects\envmodel\test\b.h(5):错误 C2143:语法错误: 失踪 ';'在''之前 1>c:\users\user\documents\visual studio 2010\projects\envmodel\test\b.h(5):错误 C4430:缺少类型 说明符 - 假定为 int。注意:C++ 不支持默认整数 1>c:\用户\用户\文档\视觉工作室 2010\projects\envmodel\test\b.h(5):错误 C4430:缺少类型 说明符 - 假定为 int。注意:C++ 不支持 default-int

还有两点我想澄清一下:

  1. 如何以及何时在 Visual Studio 2010 中使用 #include "stdafx.h"(我真的很讨厌这个 IDE,但它似乎是唯一一个与 C++ 兼容的 IDE - Netbeans 完全是这种语言的垃圾)

  2. 如何正确使用#pragma once?我假设我只是把它放在每个文件的第一行(好吧,显然这并不能解决我的问题!)。另外,它应该放在#include "stdafx.h" 之前还是之后?注意:我没有在 stdafx.h 中放一次#pragma

谢谢。

编辑:我忘记了分号,因此原来的错误跟踪是臃肿的。 Edit2:我忘了使用指针。我的实际程序确实使用了指针而不是普通的对象值,我在匆忙创建一个小示例时忽略了这一点。

【问题讨论】:

  • 您需要在类定义的末尾使用分号
  • SO 帖子每个帖子应该有一个问题。如果您还有更多问题,请发布更多帖子。
  • 相对于头文件的#ifndef#define 指令,您将#pragma once 放在哪里? - 你说“我假设我只是把它放在每个文件的第一行”。但它不应该遵循#define 指令吗?
  • C++ 不是 Java。对象变量不是引用。
  • 由于您不了解该语言,因此您可能不会知道足够的知识来判断它的 IDE。

标签: c++ include pragma


【解决方案1】:

你不能有循环依赖。

这样想。如果您实例化类型 A 的对象;那么它有多大?答案是无限大的。所以无论如何你都不能创建这样的圆形对象。

您需要使用可选值(指针)来打破循环。
因此,如果您将 B 更改为持有指向 A 的指针并使用前向引用,那么它就可以工作。

#pragma once
class A; // Forward reference.

class B {
    public: A* a; // Break cycle with a pointer. (In real life use a smart pointer)
}

注意:您仍应在头文件中使用#pragma once

【讨论】:

  • 抱歉,这是一个疏忽。看来前向参考是我错过的。我尝试使用具有相同设置的 A、B 和 C 类的方法(A、B、C 具有彼此的指针)并且它有效。我认为奇怪的一件事是 C++ 给人的印象是它只允许在同一个命名空间中的东西被声明一次,这就是为什么前向引用技巧从来没有出现在我身上的原因。对此表示赞同。
【解决方案2】:

不,#pragma once 并没有解决循环依赖问题,而不是标准的包含保护。你所做的本质上是一个递归结构,你不能有一个使用普通值的递归结构,因为这意味着sizeof(T) == infinity。这里的解决方案是:

  1. 在 A.h. 中不包括 B.h。
  2. 使用std::unique_ptr(或者只是一个原始指针,如果它不拥有该实例)而不是普通值将B 实例保存在A 中。

反之亦然,具体取决于您的课程实际上是什么。当然,最好的解决方案是在设计级别完全摆脱循环依赖(重构公共部分,诸如此类)。

stdafx.h 不相关(名称只是一个约定)- 搜索“预编译头”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-15
    • 2016-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-09
    • 2011-02-27
    • 1970-01-01
    相关资源
    最近更新 更多