为什么我在这里遭受循环依赖?
Why am I suffering Circular Dependency here?
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"
包含了它)。它给了我 "typical" 循环依赖错误 `:
syntax error: missing ';' before '*' (compiling source file ..\..\..\IPlug_AddOns\Utilities.cpp)
我哪里错了?
Utilities.h包括MyFirstCairoPlugin.h,MyFirstCairoPlugin.h包括Utilities.h,也就是一个圆圈,逻辑上造成圆圈依赖。
这是你应该做的:
如果 class 在声明中需要另一个 class,或者如果它显然是声明中最重要的部分,请将其包括在内。示例:class "Image" 可能包含 class "Color"
如果 class 在某种程度上使用另一个 class,比如将它存储在指针中或在某些方法的调用中使用它,请使用前向声明。
如果它根本不需要另一个 class,那么它也不需要。
对于第二种情况,实现文件将包含相关的 class.
在你的例子中,MyFirstCairoPlugin 存储了一个指向 Utilities 的指针,所以它应该做一个 Utilities 的前向声明,但不包括它。顺便说一下,那个指针不应该是 public.
这里应该是这样的:
#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
...
另一方面,Utilities 甚至不使用 MyFirstCairoPlugin,所以我们这里有第三种情况。为什么首先要让它包含 MyFirstCairoPlugin?如果那个宏可能是 MyFirstCairoPlugin,那么没问题,它已经有一个前向声明。不过,不会通过宏来做到这一点。而是将实用程序作为模板 class。顺便说一句,"Utilities"是一个相当宽泛的名字,听起来很容易导致名字冲突。
可能看起来像这样:
#ifndef _UTILITIES_
#define _UTILITIES_
template<class T>
class Utilities
{
private:
T* pPlug;
public:
Utilities(T* plug);
...
编辑:您似乎对模板不满意,这是另一种可能性:
创建一个抽象class(/接口),MyFirstCairoPlugin 将是其子class,提供实用程序实现中所需的所有方法。假设它叫做 "Plugin"。看起来你已经有一些像这样的 class,但由于我不知道 IPlug 是什么,所以我用了另一个名字。
围绕插件而不是 MyFirstCairoPlugin 或 PLUG_CLASS_NAME 构建实用程序。然后简单地为它提供一个 MyFirstCairoPlugin 的实例,然后它就是一个有效的插件实例。只要 Plugin 的方法是抽象和虚拟的,调用 Plugin 指针上的方法就会调用 MyFirstCairoPlugin 的方法,大家都很高兴。
一步一步看它是如何包含的:
- 在 Utilities.cpp 中,您包括
Utilities.h
- 现在你
#define _UTILITIES_
- 那么你就包含
MyFirstCairoPlugin.h
- 在那里你再次包含
Utilities.h
- 但是由于
#ifndef _UTILITIES_
,不包括 class 定义 - _UTILITIES_
已经定义(见第二步)!
所以class Utilities
还没有定义,需要前置声明
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"
包含了它)。它给了我 "typical" 循环依赖错误 `:
syntax error: missing ';' before '*' (compiling source file ..\..\..\IPlug_AddOns\Utilities.cpp)
我哪里错了?
Utilities.h包括MyFirstCairoPlugin.h,MyFirstCairoPlugin.h包括Utilities.h,也就是一个圆圈,逻辑上造成圆圈依赖。
这是你应该做的:
如果 class 在声明中需要另一个 class,或者如果它显然是声明中最重要的部分,请将其包括在内。示例:class "Image" 可能包含 class "Color" 如果 class 在某种程度上使用另一个 class,比如将它存储在指针中或在某些方法的调用中使用它,请使用前向声明。 如果它根本不需要另一个 class,那么它也不需要。 对于第二种情况,实现文件将包含相关的 class.
在你的例子中,MyFirstCairoPlugin 存储了一个指向 Utilities 的指针,所以它应该做一个 Utilities 的前向声明,但不包括它。顺便说一下,那个指针不应该是 public.
这里应该是这样的:
#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
...
另一方面,Utilities 甚至不使用 MyFirstCairoPlugin,所以我们这里有第三种情况。为什么首先要让它包含 MyFirstCairoPlugin?如果那个宏可能是 MyFirstCairoPlugin,那么没问题,它已经有一个前向声明。不过,不会通过宏来做到这一点。而是将实用程序作为模板 class。顺便说一句,"Utilities"是一个相当宽泛的名字,听起来很容易导致名字冲突。
可能看起来像这样:
#ifndef _UTILITIES_
#define _UTILITIES_
template<class T>
class Utilities
{
private:
T* pPlug;
public:
Utilities(T* plug);
...
编辑:您似乎对模板不满意,这是另一种可能性:
创建一个抽象class(/接口),MyFirstCairoPlugin 将是其子class,提供实用程序实现中所需的所有方法。假设它叫做 "Plugin"。看起来你已经有一些像这样的 class,但由于我不知道 IPlug 是什么,所以我用了另一个名字。
围绕插件而不是 MyFirstCairoPlugin 或 PLUG_CLASS_NAME 构建实用程序。然后简单地为它提供一个 MyFirstCairoPlugin 的实例,然后它就是一个有效的插件实例。只要 Plugin 的方法是抽象和虚拟的,调用 Plugin 指针上的方法就会调用 MyFirstCairoPlugin 的方法,大家都很高兴。
一步一步看它是如何包含的:
- 在 Utilities.cpp 中,您包括
Utilities.h
- 现在你
#define _UTILITIES_
- 那么你就包含
MyFirstCairoPlugin.h
- 在那里你再次包含
Utilities.h
- 但是由于
#ifndef _UTILITIES_
,不包括 class 定义 -_UTILITIES_
已经定义(见第二步)!
- 但是由于
所以class Utilities
还没有定义,需要前置声明