2017-09-29 9 views
1

'WindowList'클래스로 내 창을 관리하려고 할 때 순환 종속성에 문제가 있습니다. 아래 closeButtonPressed 코드로 창을 닫으려면 windowList 파일에서 개체를 제거해야하지만 WindowList 파일에 WindowSetter를 포함합니다. 이와 같은 이전 오류는 앞으로 선언을 통해 해결할 수 있지만이 문제를 해결하는 방법을 잘 모릅니다. 애니 제안? (전체 코드는 여기에서 볼 수 있습니다 : https://gist.github.com/anonymous/7d43c6d5b2cf1fef618be9f75077ad0c)불완전 유형 InNested 이름 지정자 JUCE

#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

OMGtechy의 반응은 당신이 묻는 질문을 해결,하지만 난 다른 디자인을 추천하고 싶은 것을 :

  1. 더 관용적 JUCE 코드가 순환 의존성에 대해 걱정할 필요가 없습니다.

여기있는 디자인은 긴밀히 연결됩니다. 이 문제를 해결하기위한보다 까다로운 방법은 그 단단한 결합을 제거하기 위해 ChangeBroadcaster/ChangeListener 클래스를 사용하는 것입니다. WindowListWindowSetter을 추가 할 때도 변경 메시지를 구독하십시오. 사용자가 닫기 버튼을 클릭하면 WindowSetter은 부울을 설정하고 청취자에게 청취자에게 업데이트되었음을 ​​알립니다. 당신은 JUCE 코드베이스에 거의 모든 곳에서 사용되는 디자인의이 종류를 볼 수 있습니다

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); 
     } 
     } 
    } 

}; 

처럼 스케치에서

, 그것은 보인다.

+0

이것은 정확하게 내가 찾는 해결책의 종류입니다! JUCE/C++에서의 hello world보다 여전히 새로운 것 – Jefferson

+1

JUCE 예제의 소스를 읽는 데 반복되는 시간이 반복됩니다. – bgporter

1

은 이제 살펴 보겠습니다하여 상상의 컴파일러의 관점에서 코드를 작성하여 무슨 일이 일어나고 있는지 확인하십시오.

의 해당 파일을 살펴 가서 여기에 포함 ...

// NOTE: we're in WindowList.h 

#include "WindowSetter.h" 

물론이지, 이제 살펴 가자 ...

// NOTE: we're back in WindowSetter.h 

#include "WindowList.h" 

을하지만 ... 난 그냥하고 있었다 그. 세상에, 나는 무한 루프에있다. 도움!

터져 죽자

둘 다 무한 루프에 서로를 필요로하기 때문에 컴파일러는, 당신이 요구하고있는 헤더를 포함 할 수 없습니다. 이 재귀 적 방식으로 헤더를 포함하지 않음으로써이주기를 깨뜨릴 필요가 있습니다.

이미 알고있는 전달 선언이 유용 ​​할 수 있습니다. 이유는 헤더를 포함하지 않아도 컴파일러에 유형 이름을 알릴 수 있기 때문입니다. 이것은 컴파일러가 타입 이름에 대해서 알 필요가 있지만 크기 (예를 들어, 크기와 같은)를 알 필요가 없을 때 유용합니다. 당신의 헤더를 포함한 결국 이유는 아마도

WindowList::getWindowList();  // ERROR: Incomplete type 'WindowList' named in nested name specifier 

:

당신이 그래도 여기있어 문제, 옆으로 건축 문제는, 당신이 여기 WindowSetter 내부 WindowList의 내부를 사용하고 있다는 것입니다 처음; 그렇지 않으면 비슷한 오류가 발생합니다.

이 문제를 해결하려면 헤더 파일 외부의 .cpp 파일로 멤버 함수 closeButtonPressed()의 정의를 이동할 수 있습니다. 일관성을 위해 다른 기능들도 옮기고 싶을 것입니다 (개인적인 의견).

이 작업을 완료하면 더 이상 WindowList의 세부 정보를 WindowSetter.h에 더 이상 사용하지 않아 더 이상 포함시키지 않게됩니다.

다른 순환 숨김이 다른 곳에 숨겨져 있지 않으면 (이 모든 것을 읽지 않은 경우) 문제를 해결할 수 있습니다.

+1

그런 자세한 설명을 보내 주셔서 감사합니다. OMGtech! 문제는 내가 포함 된 것을 사용하는 것과 관련이 있다고 생각했지만 그런 문제에 접근하는 '표준'방법이 무엇인지 확실하지 않았습니다. 미래에 이러한 문제를 처음부터 처리하는 것을 피하기위한 제안은 무엇입니까? – Jefferson

+1

@bgporter가 대부분을 커버했다고 생각합니다 :) 인터페이스는 생각할 수있는 것이 하나 더 있습니다. 인터페이스를 정의하고 클래스가이 인터페이스를 준수하는 알 수없는 유형의 객체를 가져 오게합니다. 그런 식으로, 당신은 어떤 수업을 듣든 상관하지 않습니다. 당신이 할 수있는 일에 관심이 있습니다. 그것 이외의 다른 것들은 이런 실수를하고 그들로부터 배웁니다;) 실수는 끔찍한 괴물이 아닌 기회입니다. – OMGtechy