错误"pure virtual method called",当此方法已被覆盖时

Error"pure virtual method called",when this method has been override

本文关键字:此方法 覆盖 pure virtual method called 错误      更新时间:2023-10-16

我正在尝试练习"观察者设计模式"。当我认为抽象的纯虚拟方法已被其派生类覆盖时,发生了错误。

有一个观察器,它是独立文件中的抽象类:

#ifndef DESIGN_PATTERNS_OBSERVER_H
#define DESIGN_PATTERNS_OBSERVER_H
#include "subject.h"
class Subject;
class Observer{
protected:
Observer();
public:
virtual ~Observer();
virtual void update(Subject *the_changed_subject) = 0;
};
Observer::Observer() {}
Observer::~Observer() {}
#endif //DESIGN_PATTERNS_OBSERVER_H

观察者定义了一个纯虚拟方法"更新",其覆盖如下:

#ifndef DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#define DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#include <iostream>
#include "observer.h"
#include "concrete_subject.h"
class ConcreteObserver : public Observer{
public:
void update(Subject *the_changed_subject) override {
auto cs = dynamic_cast<ConcreteSubject *>(the_changed_subject);
std::cout << "status changed to " << cs->get_status() << std::endl;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_OBSERVER_H

还有一个主题也是一个抽象类。错误"纯虚拟方法调用"发生在我标记的"通知"方法中。

从调试来看,"通知"似乎使用Observer的"更新"而不是ConcreteObserver的"更新"。

但是,在主函数中,_observers应该存储覆盖"更新"的 ConcreteObserver 的指针。

#ifndef DESIGN_PATTERNS_SUBJECT_H
#define DESIGN_PATTERNS_SUBJECT_H
#include <list>
#include "observer.h"

class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
#endif //DESIGN_PATTERNS_SUBJECT_H

它有一个派生类"ConcreteSubject":

#ifndef DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#define DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#include "subject.h"
class ConcreteSubject : public Subject {
private:
int status;
public:
ConcreteSubject() {
status = 0;
}
void set_status(int s) {
this->status = s;
Subject::notify();
}
int get_status() {
return status;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_SUBJECT_H

主要功能:

#include <iostream>
#include <vector>
#include "singleton.h"
#include "observer/concrete_subject.h"
#include "observer/concrete_observer.h"
void test2() {
ConcreteSubject concreteSubject;
std::vector<ConcreteObserver> observers;
for (int i = 0; i < 5; ++i) {
ConcreteObserver observer = ConcreteObserver();
concreteSubject.attach(&observer);
observers.push_back(observer);
}
concreteSubject.set_status(2);
}
int main() {
test2();
return 0;
}

正如我之前提到的,ConcreteSubject的超类Subject的_observers应该存储已经覆盖"更新"的ConcreteObserver的指针。 我不明白为什么观察家的"更新"仍然打电话。

这是另一件奇怪的事情。我做了一个小测试,与我展示的类关系几乎相同。但没有发生错误。

class ABaseA{
public:
virtual void do_some() = 0;
};
class MidA : public ABaseA{
public:
void do_some() override {
cout << "real do some" << endl;
}
};
class ABaseB{
private:
list<ABaseA*> *bases;
public:
ABaseB() {
bases = new list<ABaseA*>();
}
virtual ~ABaseB() = default;
virtual void add(ABaseA* item) {
bases->push_back(item);
}
virtual void do_active() {
for(ABaseA *p : *bases) {
p->do_some();
}
}
};
class MidB : public ABaseB{
public:
MidB() = default;
void active() {
ABaseB::do_active();
}
};
void test3() {
MidA midA;
MidB midB;
midB.add(&midA);
midB.active();
}

唯一的区别是此代码位于一个文件中。

在 Subject.h 的文件中,您应该将以下代码传输到 Subject.cpp:

Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}

此外,您应该在主题.h的顶部添加class Observer;

#include <list>
#include "Observer.h"
class Observer; //you should be add this line
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};