я получаю наблюдатель типа ошибки, который не может быть разрешен, когда наблюдатель является классом

У меня возникла проблема с использованием предварительно написанного кода шаблона проектирования obvserver для C++. В методе присоединения говорится, что тип Observer не может быть разрешен, когда он объявлен как класс. Кто-нибудь может помочь мне решить эту проблему? У меня также есть другая проблема с views.push_back в этом методе. Выдает ошибку «Недопустимые аргументы, кандидаты недействительны push_back (Observer * const &)». Я новичок в C++ и не совсем понимаю эти ошибки.

#include <iostream>
#include <vector>
using namespace std;

class Subject {
    // 1. "independent" functionality
    vector < class Observer * > views; // 3. Coupled only to "interface"
    int value;
  public:
    void attach(Observer *obs) {
        views.push_back(obs);
    }
    void setVal(int val) {
        value = val;
        notify();
    }
    int getVal() {
        return value;
    }
    void notify();
};

class Observer {
    // 2. "dependent" functionality
    Subject *model;
    int denom;
  public:
    Observer(Subject *mod, int div) {
        model = mod;
        denom = div;
        // 4. Observers register themselves with the Subject
        model->attach(this);
    }
    virtual void update() = 0;
  protected:
    Subject *getSubject() {
        return model;
    }
    int getDivisor() {
        return denom;
    }
};

void Subject::notify() {
  // 5. Publisher broadcasts
  for (int i = 0; i < views.size(); i++)
    views[i]->update();
}

class DivObserver: public Observer {
  public:
    DivObserver(Subject *mod, int div): Observer(mod, div){}
    void update() {
        // 6. "Pull" information of interest
        int v = getSubject()->getVal(), d = getDivisor();
        cout << v << " div " << d << " is " << v / d << '\n';
    }
};

class ModObserver: public Observer {
  public:
    ModObserver(Subject *mod, int div): Observer(mod, div){}
    void update() {
        int v = getSubject()->getVal(), d = getDivisor();
        cout << v << " mod " << d << " is " << v % d << '\n';
    }
};

person hippoman    schedule 20.03.2019    source источник
comment
Вы можете добавить прямую ссылку для Observer над определением class Subject.   -  person MFisherKDX    schedule 21.03.2019
comment
что это обозначает? извините, я относительно новичок в этом   -  person hippoman    schedule 21.03.2019
comment
если я поменяю их местами, я просто получу то же самое в Observer с Subject. Есть ли что-нибудь вокруг этого?   -  person hippoman    schedule 21.03.2019
comment
предварительное объявление — это просто строка class Observer;, расположенная над определением class Subject { ... . По сути, это говорит компилятору рассматривать Observer как тип класса... компилятор еще не будет знать размер типа или сможет получить доступ к его членам (пока не увидит определение класса), но он будет знать размер указателя на класс Observer. Таким образом, вы можете определить вектор, содержащий Observer *, без полного определения класса Observer.   -  person MFisherKDX    schedule 21.03.2019


Ответы (1)


Проблема в том, в каком порядке вы объявили свои классы. Класс Subject использует класс Observer, но Observer был объявлен позже, поэтому, когда компилятор пытается скомпилировать Subject, он не знает, что такое Observer. Однако, поскольку Subject также использует Observer, вы не можете просто изменить порядок объявления.

Ответ на эту загадку состоит в том, чтобы объявить класс Observer, чтобы компилятор, по крайней мере, знал, что Observer — это класс, даже если он мало что знает о нем. Добавьте class Observer; перед определением class Subject. Вы также можете удалить слово class из объявления вашего вектора.

class Observer;

class Subject {
    // 1. "independent" functionality
    vector < Observer * > views; // 3. Coupled only to "interface"
    ...
person john    schedule 20.03.2019