所以我遇到了这个问题,我一直在为我的OOP考试练习,而且我已经尝试过构建一个观察者设计模式。 不幸的是,似乎每次我初始化一个接口时,它都会以某种方式制作我的控制器的副本,这意味着观察者列表的新副本。因此,我的界面没有更新。
我的观察员:
#pragma once
#include <vector>
#include <algorithm>
class Observer
{
public:
virtual void update() = 0;
virtual ~Observer() {}
};
class Observable
{
private:
std::vector<Observer*> observers;
public:
virtual ~Observable() {}
void addObserver(Observer *obs)
{
observers.push_back(obs);
}
void removeObserver(Observer *obs)
{
observers.erase(std::remove(observers.begin(), observers.end(), obs));
}
void notify()
{
for (auto obs : observers)
{
obs->update();
}
}
};
这是需要更新的界面:
class Practice : public QWidget, public Observer
{
Q_OBJECT
public:
Practice(Controller& ctrl, Teacher& t, QWidget *parent = Q_NULLPTR);
--------------
Practice::Practice(Controller& ctrl, Teacher& t, QWidget *parent) : ctrl{ ctrl }, t{ t }, QWidget(parent)
{
ui.setupUi(this);
QObject::connect(ui.studentList, &QListWidget::itemSelectionChanged, this, [this]() {this->listItemChanged(); });
QObject::connect(ui.gradeButton, &QPushButton::clicked, this, &Practice::on_gradeButton_clicked);
this->populateStudentsList();
this->ctrl.addObserver(this);
}
我的主要人物:(我打开的窗户数量与#34;教师和#34相同;)
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Repository repo("Student.txt", "Teacher.txt");
Controller ctrl(repo);
std::vector<Teacher> temp = ctrl.getRepo().getTeachers();
for (int i = 0; i < temp.size(); ++i)
{
Practice* p = new Practice{ctrl, temp[i]};
p->setWindowTitle(QString::fromStdString(temp[i].getName()));
p->show();
}
return a.exec();
}
另外,我的控制器继承自Observable。
我对它进行了调试,我得出的结论是每次初始化&#34;练习&#34;时都会创建一个新的控制器。而且我不知道为什么。
谢谢。
答案 0 :(得分:1)
我调试了它,我得出的结论是每次初始化“练习”时都会创建一个新的控制器而我不知道为什么。
您没有显示Practice
类的完整声明,但从构造函数定义可以清楚地看出,该类中存在ctrl
成员。< / p>
如果ctrl
成员未被声明为引用(Controller&
),那么当构造函数在成员初始化列表中调用ctrl{ ctrl }
时,副本即使输入ctrl
对象通过引用传递给构造函数,也会生成输入ctrl
对象。
如果Controller
对象的意图比Practice
对象更长(似乎是这种情况),那么考虑使Practice::ctrl
成员成为输入的引用/指针{ {1}}对象,而不是它的副本:
Controller
或者:
class Practice : public QWidget, public Observer
{
...
private:
Controller &ctrl;
...
public:
Practice(Controller& ctrl, ...);
~Practice();
...
};
Practice::Practice(Controller& ctrl, ...) : ctrl{ ctrl }, ...
{
...
this->ctrl.addObserver(this);
}
Practice::~Practice()
{
...
this->ctrl.removeObserver(this);
}
或者,考虑将class Practice : public QWidget, public Observer
{
...
private:
Controller *ctrl;
...
public:
Practice(Controller& ctrl, ...);
~Practice();
...
};
Practice::Practice(Controller& ctrl, ...) : ctrl{ &ctrl }, ...
{
...
this->ctrl->addObserver(this);
}
Practice::~Practice()
{
...
this->ctrl->removeObserver(this);
}
对象包裹在Controller
内,然后将std::shared_ptr<Controller>
成员声明为Practice::ctrl
以匹配。
std::shared_ptr<Controller>
无论哪种方式,多个class Practice : public QWidget, public Observer
{
...
private:
std::shared_ptr<Controller> ctrl;
...
public:
Practice(std::shared_ptr<Controller> ctrl, ...);
...
};
Practice::Practice(std::shared_ptr<Controller> ctrl, ...) : ctrl{ ctrl }, ...
{
...
this->ctrl->addObserver(this);
}
Practice::~Practice()
{
...
this->ctrl->removeObserver(this);
}
int main()
{
std::shared_ptr<Controller> ctrl = std::make_shared<Controller>(repo);
...
Practice* p = new Practice{ctrl, temp[i]};
...
}
对象都可以共享一个Practice
对象。
答案 1 :(得分:0)