不完整类型InNested Name Specifier JUCE

时间:2017-09-29 12:13:33

标签: c++ juce

我尝试使用' 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;
};

enter image description here

编辑:添加导致错误的文件的完整代码和错误日志屏幕截图

2 个答案:

答案 0 :(得分:2)

OMGtechy的回复解决了您提出的问题,但我想推荐一种不同的设计:

  1. 消除了担心循环依赖的需要
  2. 是更惯用的JUCE代码。
  3. 这里的设计将各种事物紧密地结合在一起。解决问题的更多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.hproduct_adapter.clear(); CharSequence[] array=makeArray(urlMaker.getProductid()); for(int i=0;i<array.length;i++){ product_adapter.add(array[i]); } product_adapter.notifyDataSetChanged(); 的详细信息,因此可以停止包含该内容。

这将解决您的问题,除非其他地方隐藏了其他循环依赖项(我还没有全部阅读过。)