我尝试使用' WindowList'来管理我的窗口时遇到循环依赖问题。类。当我想用下面的closeButtonPressed代码关闭一个窗口时,我需要从windowList文件中删除该对象,但是我在WindowList文件中包含了WindowSetter。像这样的先前错误已通过前向声明解决,但我不知道如何解决这个问题。安妮的建议? (完整代码可在此处查看:https://gist.github.com/anonymous/7d43c6d5b2cf1fef618be9f75077ad0c)
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
#include "WindowList.h"
class WindowList;
class WindowSetter : public DialogWindow
{
public:
WindowSetter (const String& title,
Component* content,
bool shouldBeResizeable,
int initWidth, int initHeight,
int minWidth, int minHeight,
int maxWidth, int maxHeight)
: DialogWindow (title, Colours::white, true, true),
owner (this)
{
setUsingNativeTitleBar (true);
setResizable (true, true);
setResizeLimits (minWidth, minHeight, maxWidth, maxHeight);
setContentOwned (content, false);
setVisible (true);
}
~WindowSetter()
{
}
void closeButtonPressed() override
{
WindowList::getWindowList(); // ERROR: Incomplete type 'WindowList' named in nested name specifier
owner = nullptr;
}
bool escapeKeyPressed() override
{
return true;
}
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowSetter)
ScopedPointer<Component> owner;
};
编辑:添加导致错误的文件的完整代码和错误日志屏幕截图
答案 0 :(得分:2)
OMGtechy的回复解决了您提出的问题,但我想推荐一种不同的设计:
这里的设计将各种事物紧密地结合在一起。解决问题的更多JUCE-y方法是使用ChangeBroadcaster
/ ChangeListener
类来消除紧密耦合。向WindowSetter
添加WindowList
时,也会订阅其更改消息。当用户点击关闭按钮时,WindowSetter
会设置一个布尔值,并提醒任何听到它的人都已更新。
在草图中,它看起来像
class WindowSetter : public DialogWindow
, public ChangeBroadcaster
{
public:
WindowSetter( /*(etc...)*/)
: DialogWindow(...)
, owner(this)
, wantsToClose(false)
{
// etc
}
void closeButtonPressed() override
{
wantsToClose = true;
// notify observers that we've changed.
sendChangeMessage();
}
bool windowWantsToClose() const
{
return wantstoClose;
}
private:
bool wantsToClose;
};
class WindowList : public ChangeListener
{
void addWindowSetterToList(WindowSetter* wnd)
{
wnd->addChangeListener(this)
windows.addIfNotAlreadyThere(wnd);
}
void changeListenerCallback(ChangeBroadcaster* src) override
{
// cast from the ChangeBroadcaster base class to our WindowSetter class.
WindowSetter* wnd = dynamic_cast<WindowSetter*>(src);
if (nullptr != wnd)
{
// if we contain the object, and the object wants to be closed...
if (windows.contains(wnd) && wnd->windowWantsToClose())
{
// get rid of it.
windows.remove(wnd);
}
}
}
};
你会看到这种设计在JUCE代码库中几乎无处不在。
答案 1 :(得分:1)
让我们从一个想象的编译器的角度看一下你的代码,看看发生了什么......
// NOTE: we're in WindowSetter.h
#include "WindowList.h"
当然,让我们去看看那个文件并把它包含在这里......
// NOTE: we're in WindowList.h
#include "WindowSetter.h"
当然,我们去看看......
// NOTE: we're back in WindowSetter.h
#include "WindowList.h"
但是......我只是这样做。天哪,我处于无限循环中。帮助!
<强> KABOOM 强>
编译器不能包含您要求的标头,因为它们在无限循环中都需要彼此。您需要通过不以此递归方式包含标头来打破此循环。
您已经了解的前向声明对此非常有用。原因是因为他们可以在不必包含标题的情况下通知编译器类型名称。如果编译器只需要知道类型名称,那就太好了,但没有别的(比如大小)。
你遇到的问题是,除了架构问题之外,你在WindowList
WindowSetter
内部使用了 WindowList::getWindowList(); // ERROR: Incomplete type 'WindowList' named in nested name specifier
的内部:
closeButtonPressed()
这可能就是为什么你最终将头部包括在内;如果你没有,它会给你一个类似的错误。
要解决此问题,您可以将成员函数WindowList
的定义移到头文件之外,并转移到.cpp文件中。为了一致性,你可能也想移动其他功能(个人观点)。
完成后,您将不再使用WindowSetter.h
内product_adapter.clear();
CharSequence[] array=makeArray(urlMaker.getProductid());
for(int i=0;i<array.length;i++){
product_adapter.add(array[i]);
}
product_adapter.notifyDataSetChanged();
的详细信息,因此可以停止包含该内容。
这将解决您的问题,除非其他地方隐藏了其他循环依赖项(我还没有全部阅读过。)