0

我正在学习 OOP 并且有疑问。假设我有一个包含ClassA.h的文件ClassB.h,并且在某些时候我的ClassB.h需要包含ClassA.h

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

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

4

3 回答 3

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

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

根据问题,您可以使用多种技术之一:

  • 从公共基类继承
  • 将两个类中的一个转换为另一个的基类- 这是前一个的变体。
  • 前向声明 - 这不是那么理想,因为它并没有真正打破循环依赖,它只是安排它,所以你不需要也有一个有问题的循环包含依赖。
  • 将两个类的某些部分变成一个它们都可以使用的类- 这是通用基类的另一种变体,它使用组合而不是继承。

还有其他技术。事实上,有一本书在各种情况下使用了非常广泛的技术,因为消除循环依赖是这本书的一个重要主题。那本书是John Lakos 的“Large-Scale C++ Software Design”

于 2013-02-15T01:32:31.897 回答
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
于 2013-02-15T01:52:45.103 回答
-1

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

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

然后我解决了“递归包含问题”

于 2013-02-15T01:44:23.237 回答