【问题标题】:Circular includes in C++ - again [duplicate]C ++中的循环包含 - 再次[重复]
【发布时间】:2013-05-06 18:07:49
【问题描述】:

Main.cpp

#include "Test1.h"
#include "Test2.h"

int main(){  
    Test1 t1;
    Test2 t2;

    t1.process(t2);
    t2.process(t1);

} 

Test1.h

#ifndef TEST1
#define TEST1

#include "Test2.h"

class Test1 {
public:
    void process(const Test2& t) {};
};


#endif // !TEST1

Test2.h

#ifndef TEST2
#define TEST2

#include "Test1.h"

class Test2 {
public:
    void process(const Test1& t) {};
};


#endif // !TEST2

VS2012 说:

error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2143: syntax error : missing ',' before '&'
error C2664: 'Test2::process' : cannot convert parameter 1 from 'Test1' to 'const int'

我很确定这又是 循环包含 问题(我偶尔会遇到它),但这次我不确定为什么不编译。

注意:这些类只依赖于彼此的引用,它们的大小是已知的。是因为包含保护 (#ifndef),导致其中一个测试标头包含另一个作为空文件吗?

【问题讨论】:

  • 为什么需要包含? *.h 中的前向声明就足够了。
  • 这有数百万个重复项。发帖前请努力研究问题。
  • here,很好的解释。在决定是转发声明还是包含时,您可以根据经验使用它。

标签: c++ circular-dependency


【解决方案1】:

如果您坚持这样做,您需要在每个 .h 文件中转发声明您的类,以便编译器知道它是什么。

#include "Test1.h"

class Test1;

class Test2 {
public:
    void process(const Test1& t) {};
};

【讨论】:

  • 转发声明 class Test1' allows you to declare pointers to Test1, not implementing references. Also #include` 似乎不在这里。
  • @CaptainGiraffe:“实施参考”是什么意思?!
  • 问题关闭太快,我无法调整任何内容。哦,好吧。
  • @KerrekSB 为void process(const Test1& t){ .... } 编写实现。我为我草率的语言道歉。过失。
  • 但是为什么我必须转发声明 Test1,当它就在那里时 - 在包含的 Test1.h 中?
【解决方案2】:

完全展开预处理器指令,您会看到问题:Main.cpp 包含 Test1.h,其中包含 Test2.h,因此 class Test2 将首先编译,然后再定义 Test1,导致 @ 987654323@ 错误。您可以通过前向声明 Test1 并说 void process(const class Test1& t) 而不仅仅是 void process(const Test1& t) 来解决此问题。

【讨论】:

  • 但是为什么我需要在Test2中定义Test1,我只在方法签名中使用了引用;它的大小已知。我什至不调用任何方法
  • 对于 C++,这还不够;它不知道 Test1 在这一点上是什么,所以它不知道它是一个类型还是别的什么。当然,C++ 可以推断出Test1 是一种类型,但这并不是该语言的设计方式。你必须明确说Test1 是一种类型,然后才能使用它;要么完全声明类型,要么将其前向声明为类型。
【解决方案3】:

您需要将其中一个的前向声明放在另一个的标题中。如果您在 Test2.h 中转发声明 Test1(在声明 Test2 之前),您可以从 Test2.h 中删除 #include "Test1.h"

【讨论】:

    【解决方案4】:

    如果您在标头中有类型的引用或指针,请尝试使用前向声明。

    // Within stop Test2.h
    class Test1;
    

    【讨论】:

      【解决方案5】:

      test1.htest2.h 中,您可以分别使用Test2Test1 的前向声明来避免包含。只需将class Test1; 替换为#include "test1.h"

      然后只在实现文件中包含test1.h

      看到这个question

      【讨论】:

        猜你喜欢
        • 2011-06-08
        • 1970-01-01
        • 2017-11-16
        • 1970-01-01
        • 1970-01-01
        • 2010-12-11
        • 2013-07-25
        • 2013-09-19
        • 1970-01-01
        相关资源
        最近更新 更多