为什么我在这里遭受循环依赖?

时间:2016-12-06 09:05:22

标签: c++ circular-dependency forward-declaration

Utilities.h

#ifndef _UTILITIES_
#define _UTILITIES_

#include "MyFirstCairoPlugin.h"

class PLUG_CLASS_NAME;

class Utilities
{
private:
    PLUG_CLASS_NAME *pPlug;

public:
    Utilities(PLUG_CLASS_NAME *plug);
    ~Utilities();
};

#endif // !_UTILITIES_

Utilities.cpp

#include "Utilities.h"

Utilities::Utilities(PLUG_CLASS_NAME *plug) : pPlug(plug) {
    IColor color = IColor(100, 100, 100, 255);
}
Utilities::~Utilities() {

}

这是我遇到麻烦的地方,使用MyFirstCairoPlugin.h中的这句话:

#ifndef _MYFIRSTCAIROPLUGIN_
#define _MYFIRSTCAIROPLUGIN_

#include "IPlug_include_in_plug_hdr.h"
#include "resource.h"

#include "Utilities.h"

//class Utilities;

class MyFirstCairoPlugin : public IPlug
{
private:

public:
    Utilities *pUtilities;

    MyFirstCairoPlugin(IPlugInstanceInfo instanceInfo);
    ~MyFirstCairoPlugin();
};

#endif // !_MYFIRSTCAIROPLUGIN_

如果我不取消评论//class Utilities;(转发声明),则无法使用实用工具(即使我已将其包含在上面,#include "Utilities.h")。它给了我“典型的”循环依赖性错误`:

syntax error: missing ';' before '*' (compiling source file ..\..\..\IPlug_AddOns\Utilities.cpp)

我哪里错了?

2 个答案:

答案 0 :(得分:1)

Utilities.h包含MyFirstCairoPlugin.h,MyFirstCairoPlugin.h包含Utilities.h,即圆形,逻辑上导致循环依赖。

这是你应该做的事情:

如果一个类在声明中需要另一个类,或者它显然是其中最重要的部分,请包括它。示例:一个班级"图像"可能包括一个班级"颜色" 如果一个类在某种程度上使用了另一个类,比如将它存储在指针中或者在调用某个方法时使用它,请使用forward声明。 如果它根本不需要其他类,那么它也不会。 对于第二种情况,实现文件将包含依赖类。

在您的情况下,MyFirstCairoPlugin存储指向Utilities的指针,因此它应该执行Utilities的前向声明,但不包括它。顺便说一句,该指针不应该是公开的。

这里应该是这样的:

#ifndef _MYFIRSTCAIROPLUGIN_
#define _MYFIRSTCAIROPLUGIN_

#include "IPlug_include_in_plug_hdr.h" //<--- no idea what that is about
#include "resource.h"

class Utilities;

class MyFirstCairoPlugin : public IPlug
{
private:

public:
    Utilities* pUtilities; //<-- shouldn't be public, you should always use encapsulation 
...

另一方面,实用程序甚至不使用MyFirstCairoPlugin,所以我们在这里有第三种情况。为什么你首先包括MyFirstCairoPlugin?如果该宏可能是MyFirstCairoPlugin,那么没问题,它已经有一个前向声明。但是,不会在宏观上做到这一点。而是将Utilities作为模板类。顺便说一下,&#34; Utilities&#34;是一个相当广泛的名称,听起来很容易导致名称冲突。

看起来像这样:

#ifndef _UTILITIES_
#define _UTILITIES_

template<class T>
class Utilities
{
private:
    T* pPlug;

public:
    Utilities(T* plug);
...

编辑:似乎你似乎对模板不满意,这是另一种可能性:

创建一个抽象类(/接口),其中MyFirstCairoPlugin将是一个子类,提供Utilities实现中所需的所有方法。让我们说它被称为&#34;插件&#34;。看来你已经有了这样的课程,但是因为我不知道IPlug是什么,所以我选择其他名字。

围绕插件而不是MyFirstCairoPlugin或PLUG_CLASS_NAME构建实用程序。然后简单地为它提供一个MyFirstCairoPlugin实例,这是一个有效的插件实例。只要插件的方法是抽象的和虚拟的,在Plugin指针上调用方法就会调用MyFirstCairoPlugin的方法,每个人都很高兴。

答案 1 :(得分:0)

了解它是如何逐步包含的:

    在Utilities.cpp中
  • ,您包含Utilities.h
  • 现在你#define _UTILITIES_
  • 然后你包括MyFirstCairoPlugin.h
  • 在那里你再次加入Utilities.h
    • 但由于#ifndef _UTILITIES_,未包含类定义 - _UTILITIES_已定义(请参阅第二步)!

所以class Utilities尚未定义,您需要转发声明。