我正在尝试为我正在为学校项目创建的游戏实施Observer模式。
我创建了2个虚拟类,Observer和Observable。
Observer.h:
#ifndef OBSERVER_H
#define OBSERVER_H
#include <vector>
class Observable;
class Observer
{
public:
Observer();
virtual ~Observer();
virtual void update(Observable* ob) =0;
};
#endif
Observer.cpp:
#include "stdafx.h"
#include "Observer.h"
Observer::Observer()
{
}
Observer::~Observer()
{
}
Observable.h:
#ifndef OBSERVEABLE_H
#define OBSERVEABLE_H
#include <vector>
#include "Observer.h"
class Observable
{
protected:
std::vector<Observer*> observers;
public:
Observable();
virtual ~Observable();
virtual void attach(Observer *a);
virtual void detach(Observer *a);
virtual void notify();
};
#endif
Observable.cpp:
#include "stdafx.h"
#include "Observable.h"
Observable::Observable()
{
}
Observable::~Observable()
{
}
void Observable::attach(Observer *a)
{
observers.push_back(a);
}
void Observable::detach(Observer *a)
{
for (auto it = this->observers.begin(); it < this->observers.end(); it++)
{
if (*it == a)
{
this->observers.erase(it);
break;
}
}
}
void Observable::notify()
{
for (int i = 0; i < observers.size(); i++)
observers[i]->update(this);
}
我有一个继承自Observable的Map类,以及一个继承自Observer的mapView类(Map非常长,我只包含了相关的函数)
Map.h:
#ifndef MAP_H
#define MAP_H
#include "Observable.h"
#include <iostream>
class Map : public Observable
{
public:
Map();
~Map();
void getLatest();
void notify();
};
#endif
Map.cpp:
#include "stdafx.h"
#include "Map.h"
Map::Map()
{
}
Map::~Map()
{
}
void Map::getLatest()
{
using namespace std;
cout << "This is the latest info!" << endl;
}
mapView.h:
#ifndef MAP_V_H
#define MAP_V_H
#include "Observer.h"
#include "Map.h"
#include "Plants.h"
class mapView : public Observer
{
public:
mapView();
~mapView();
void update(Map* map);
};
#endif
mapView.cpp:
#include "stdafx.h"
#include "mapView.h"
#include "Map.h"
mapView::mapView()
{
}
mapView::~mapView()
{
}
void mapView::update(Map* map)
{
map->getLatest();
}
最后,我的主要创建一个Map和一个mapView,附加mapView,并调用map.notify()
main.cpp中:
#include "stdafx.h"
#include "setUp.h"
#include "Map.h"
#include "mapView.h"
int main()
{
Map gameMap;
mapView view;
gameMap.attach(&view);
gameMap.notify();
return 0;
}
我在这里遇到了很多问题。我无法创建mapView项,因为编译器说我从未实现更新的覆盖版本(Observable * ob)....我尝试使用update(Map * map)但看起来尽管Map继承自Observable,但它似乎并不算作相同的签名,所以它不会编译。
我试图改变我的mapView :: update()函数来取代一个指向Observable的指针,但这不起作用,因为该函数从Map类调用了一些东西。
然后我尝试将更新函数更改为不是虚函数(在虚拟类中使用空实现),但似乎每当我尝试传递Map进行更新时,它都会调用基类函数而不是mapView版本。换句话说,getLatest()永远不会被调用。
我现在很困惑,因为这与我认为多态性的工作方式不符。如果可能的话,会感激一些帮助或见解!
谢谢,
答案 0 :(得分:2)
您的基类声明:
virtual void update(Observable* ob) =0;
你派生的类声明:
void update(Map* map);
这些签名不一样。如果你使用了新的override
关键字,你会在编译时看到你实际上没有覆盖虚方法。
如果您知道,您只会获得Map
,那么您可以使用static_cast
。但使用dynamic_cast
:
void update(Observable* o) override { // now we're ok
if (auto map = dynamic_cast<Map*>(o)) {
// okay, got a Map
// ....
}
else {
// huh?
}
}
超级简短类型理论题外话题。覆盖的典型规则是返回的 co </ em>变体和参数类型中的 contra 变体。您可以指定更多派生的返回类型或更多基础的参数类型。以这种方式思考 - 如果你有一个基类函数并且返回Car*
...你的参数可以是Car*
(这正是预期的那样),或者它可以是{{1 (因为您可以使用Vehicle*
执行任何操作,您可以使用Vehicle
- 这仍然有效),但它不能是Car
(因为调用者可能会通过)你是一个不是SportsCar*
的{{1}},并且有理由期望这个有用!)派生类只接受Car
s是没有意义的 - 你必须能够接受任何SportsCar
,甚至不是Map
s!