2013-02-15 68 views
0

我正在学习OOP并且有疑问。假设我有一个文件ClassA.h包括ClassB.h,并在某些时候我ClassB.h需要包括ClassA.hOOP C++ - A.h的错误包括B.h,其中又包括A.h

这yelds一个错误,我想我明白了,为什么出现这种情况,因为我得到一个无限循环包含。但在这种情况下该怎么办?有没有解决这个错误的方法?还是我应该重新思考我的课程以避免它?这是否意味着我的班级组织设计不佳?如果是这样,那么安排我的“类图”并避免这种情况的方法是什么?

我只是想知道什么是在这种情况下的最佳实践。另外,为什么“#pragma Once”指令不能解决这个问题?提前致谢。

+0

它应该有一个连字符分开的称号,我会补充说,现在,遗憾的混乱。 – 2013-02-15 01:33:21

+0

通常情况下,通常会包含导致问题的实际代码的代码段。它可以是一个测试用例,只要它实际上存在你所问的问题,并且你已经测试了它,以确保它只是在这里发布。之所以这样很难给出一个很好的具体答案。 – Omnifarious 2013-02-15 01:41:20

回答

4

有一种方法可以解决它,但这也意味着你的班级组织已经坏了。

解决它的方法被称为“包括警卫,虽然很多编译器还支持#pragma once指令。我想这是行不通的,因为#pragma once可能不考虑包含头文件,直到整个事情被解析。由于递归包含发生在头文件的中间,所以还没有完成解析。

一个包括后卫是这样的:

在ClassA.h:

#pragma once // Just because. It really should help. 
#ifndef INCLUDED_CLASSA_H 
#define INCLUDED_CLASSA_H 

#include "ClassB.h" 

//... rest of header file 

#endif 

在ClassB.h:

#pragma once // Just because. It really should help. 
#ifndef INCLUDED_CLASSB_H 
#define INCLUDED_CLASSB_H 

#include "ClassA.h" 

//... rest of header file 

#endif 

组织问题被称为循环依赖,以及循环依赖通常是一个坏主意。有很多不同的方法可以打破它们,但是要使用哪种方法取决于依赖关系的确切性质和原始原因。

根据不同的问题,你可以使用各种技术之一:

从公共基类
  • 谈到这两个类中的一个成一个基类为其他
    • 继承 - 这是前一个的变体。
    • 正向声明 - 这是不希望这样,因为它并没有真正打破循环依赖,它只是安排,所以你并不需要也有一个问题圆形包括依赖性。
    • 车削两个类的某些部分成一类,它们都可以使用- 这是共同的基类的另一种变型,使用的组合物,而不是继承的。

    还有其他技术。事实上,有一本书有各种各样的技术可用于各种情况,因为消除循环依赖是本书的一大主题。那本书是"Large-Scale C++ Software Design" by John Lakos

  • +1

    那么#ifndef卫士与#pragma的工​​作方式有什么不同?无论如何,我只是测试它,并得到同样的问题。如果不好的做法,我会尝试重新排列这些东西来解决这个问题。 – 2013-02-15 01:42:51

    +1

    @LeandroNogueiraCouto:那些应该工作。什么,确切地说,你得到的错误是什么?是的,这是不好的做法。 :-)它们的工作方式不同,因为'#pragma once'由编译器在预处理器中以供应商认为合适的方式实现(因为它只是一个广泛支持的扩展)。而那些'#ifdef'后卫依靠精心指定的功能。 – Omnifarious 2013-02-15 01:43:43

    +0

    我收到了大量的错误,超过100个奇怪的语法错误和“未声明的标识符”。 了解问题的名称有很大帮助,我搜索了循环依赖关系,并发现一个简单的前向声明有助于我的特殊情况,以及涉及重构我的类的其他解决方案。 – 2013-02-15 02:23:56

    -1

    在我过去的经验中,我通过使用继承来解决了同样的问题。

    我解决的方法是。 ClassA - > ClassB:ClassB被ClassA继承。 ClassA具有ClassB和ClassA想要的共同需求。

    然后我下了决心“递归问题包括”

    +0

    #包括与继承无关的问题 - 例如,您可能与C中的#includes具有完全相同的问题,它不支持继承。 – 2013-02-15 02:17:36

    4

    您也可以解决这个问题,通过使用预先声明。假如你没有创建你在头文件中包含的类的实际对象,或者不从它继承,比方说,如果你只需要在头文件中指向它们的指针,你可以这样做。

    例子:

    ClassA.h 
    class ClassB; 
    //rest of the codes here 
    
    ClassB.h 
    class ClassA; 
    //rest of the codes here 
    
    ClassA.cpp 
    #include ClassA.h 
    #include ClassB.h 
    
    ClassB.cpp 
    #include ClassB.h 
    #inlcude ClassA.h 
    
    +0

    是的,这解决了我的问题。谢谢! – 2013-02-15 02:27:28