2017-02-01 1 views
0

Observer와 Subject의 두 클래스와 ObserverA, ObserverB는 Observer (Observer DP 구현을 위해)를 확장하고 있습니다. 모두전달 선언 불완전 유형, 재귀

class Observer { 
protected: 
    Subject subj; 
public: 
    virtual void update() {}; 
}; 

ObserverA, ObserverB :

class ObserverA: public Observer { 
public:  
    ObserverA(Subject s) { 
     subj = s; 
     s.attach(this); 
    } 

    virtual void update() { 
     std::cout << "Update A, state subj: " << subj.getState() << std::endl;  
    } 
}; 

관찰자에서
class Subject { 
    std::vector<Observer*> obs; 
    int state; 
public: 
    Subject(): state(0) {} 

    void notifyAll() { 
     for(std::vector<Observer*>::iterator it = obs.begin(); it != obs.end(); it++) 
     { 
     (*it)->update(); 
     } 
    } 
} 

... 
}; 

, 나는 또한 주제를 가지고 주제에

나는 관찰자 클래스에 대한 포인터의 벡터를 가지고

Subject 클래스를 선언하기 전에 Observer 클래스에 대한 forward 선언을 추가했습니다.

Observer.h: In member function ‘void Subject::notifyAll()’: 
Observer.h:27:17: error: invalid use of incomplete type ‘class Observer’ 
      (*it)->update(); 
       ^
Observer.h:7:7: error: forward declaration of ‘class Observer’ 
class Observer; 
^

내가 주제 클래스, 내가 앞으로 Obsever 클래스 선언에서 관찰자에 대한 포인터의 벡터를 가지고 옵저버 클래스는 Subect에 대해 알고, 왜 내가 여전히 오류가 있습니까 : 그러나 나는 컴파일 오류는 무엇입니까?

+0

실제로 클래스의 기능을 사용하려면 * 전체 정의가 필요합니다. forward 선언문 만 가지고 있다면 컴파일러는 실제로 어떤 멤버 함수를 가지고 있는지 어떻게 알 수 있습니까? –

+0

IMO, 같은 문제에 대해 "중복 된 질문"과 두 가지 질문이 다릅니다. 해결책을 알고있는 프로그래머는 답이 비슷하다는 것을 즉시 알게 될 것이지만 새로운 프로그래머는 그렇지 않을 것입니다. 아마도 그 이유는 그가 아직 답을 읽지 않고 묻는 이유 일 것입니다. –

답변

3

Subject::notifyAll의 구현을 .cpp 파일로 옮깁니다 (실제로 모든 멤버 함수 구현에서 그렇게하십시오). - subject.cpp 파일을 말하십시오. 그런 다음 Subject 클래스 정의가 들어있는 헤더 파일에 Observer의 전달 선언을 보관하고 subject.cpp에 #include "observer.hpp"을 유지합니다.

클래스 정의가 Observer*을 참조하기 때문에 헤더 파일에서 정방향 선언만으로 충분합니다. 반면에 .cpp 파일은 Observer 인스턴스의 멤버 함수를 호출하기 때문에 전체 Observer 클래스 정의를 확인해야합니다. 그래서

:

// subject.hpp 
#include <vector> 

class Observer; 

class Subject { 
    std::vector<Observer*> obs; 
    int state; 
public: 
    Subject(): state(0) {} 

    void notifyAll(); 
}; 

과 :

// subject.cpp 
#include "subject.hpp" 

#include "observer.hpp" 

#include <vector> 

void Subject::notifyAll() { 
    for(std::vector<Observer*>::iterator it = obs.begin(); it != obs.end(); it++) 
    { 
    (*it)->update(); 
    } 
} 

는 또한, 당신의 관찰자의 구현은 상당히 개선 될 수있다. 예 : :

  • ObserverSubject을 보관하지 않습니다. 같은 관찰자에 대해 여러 과목이있을 가능성이 높지만 더 중요한 것은 관찰자가 과목을 추적 할 필요가 없다는 것입니다.
  • Observer 생성자에서 SubjectObserver을 연결하지 마십시오. 그러면 관찰자 당 하나의 제목 만 가질 수 있습니다. 대신 을 Subject 생성자 (또는 다른 멤버 함수)의 Subject에 연결하십시오.
  • 복사본을 만들지 않으려면 값으로 전달하지 마십시오. 대신 참조로 전달하십시오 (예 : const Subject&).
+0

Subject 정의 이전에 Observer 정의를 이동하여 해결했으며 Observer에서는 Subject에 대한 포인터를 사용했습니다. –

+1

@georgiana_e : 코드를 다른 파일로 나누는 것을 고려해야합니다. 삶을 훨씬 쉽게 할 수 있습니다. –