问题描述
我正在尝试一种模板设计,以允许自动的观察者/观察到的功能。我有两个怀疑这个问题的人:
- 静态继承没有按照我对
Observing::notify()
的期望进行。 - 我尝试绑定到模板
TYPE::Status
类中的enum class
的{{1}}模板化参数。
TYPE
我以为#include <iostream>
#include <set>
// Observer base class
template <class TYPE>
struct Observing
{
template <class STATUS = TYPE::Status>
void notify(STATUS status);
protected:
// Constructed only through inheritance
Observing() { TYPE::subscribe(this); }
~Observing() { TYPE::unsubscribe(this); }
};
// Class being observed
template <class TYPE>
struct Observable
{
static void subscribe (Observing<TYPE>* obs) { observers.insert(obs); }
static void unsubscribe (Observing<TYPE>* obs) { observers.erase(obs); }
static std::set<Observing<TYPE>*> observers;
};
// Static deFinition of observable object's observers container
template <class TYPE>
std::set<Observing<TYPE>*> Observable<TYPE>::observers;
// Implementation of an observable service
struct Service : Observable<Service>
{
enum class Status { Up,Down };
void broadcast(Status status)
{
for (Observing<Service>* obs : observers)
obs->notify(status); // <--- unable to link `notify()`
}
};
struct Process: Observing<Service>
{
void notify(Service::Status status)
{
switch (status)
{
case Service::Status::Up: std::cout << "Service is UP\n"; break;
case Service::Status::Down: std::cout << "Service is DOWN\n"; break;
}
}
};
int main()
{
Service service;
Process worker;
service.broadcast(Service::Status::Up);
}
的定义可能为时已晚,但是我尝试将声明放在Process::notify()
上方,并将定义放在下方,但随后我必须向前声明Service
和无法找到声明Service
的方法。
也许我的方法太复杂了...
解决方法
据我了解,您要实现的功能无法正常工作。在此代码中,编译器只能在结构notify
中找到没有正文的Observing
函数。因此,链接器稍后会对此抱怨。
for (Observing<Service>* obs : observers)
obs->notify(status); // <--- unable to link `notify()`
让我们尝试帮助编译器选择正确的函数。由于我们处于编译时,因此可以使用static_cast。让我们尝试一下:
static_cast<To what?>(obj)->notify(status);
这个问题(对static_cast的答案)的答案只能在运行时获得-这导致我们动态多态。
因此,您必须尝试另一种解决方案:使用运行时多态性或更改类的体系结构。
,观察者模式的重点是主题不知道观察者的静态类型。您将需要virtual
。这意味着notify
不能作为模板,您需要修复Observable
的成员表示notify
的自变量。
template <class TYPE>
struct Observing
{
using Status = typename TYPE::Status;
virtual void notify(Status status);
// ...
};
为了安全起见,请在覆盖override
的位置添加
struct Process: Observing<Service>
{
void notify(Status status) override;
};