如何使用TR1实现观察者模式模板基类
C++ How to implement observer pattern template base class using TR1
我想实现一个类"MyClass"作为一个基础的可观察类。例如:
class Observed : public MyClass<Observed>{
public: void DoWork() {.... MyClass<Observed>::NotifyObservers();}
};
class AnyObserver {public: HandleObserved(Observed& ob){...}};
AnyObserver any;
Observed observed;
observed.AddObserver(&any, &AnyObserver::HandleObserved);
observed.DoWork();.....
以下是我到目前为止的实现。我相信这将工作得很好,除了我进入编译问题。
template <typename T>
class MyClass
{
typedef std::tr1::function<void( T& )> CallbackFunction;
std::list< CallbackFunction > m_observers;
template<class S>
struct TypeHelper
{
//I. Compilation error is here: Unexpected "...
typedef void (typename S::*Signature)(T&);
};
public:
template<class M>
void AddObserver(M& observer, TypeHelper<M>::Signature callback)
{
CallbackFunction bound = std::tr1::bind(callback, observer, tr1::placeholders::_1);
m_observers.push_back(bound);
}
protected:
void NotifyObservers()
{
std::list< CallbackFunction >::iterator iter = m_observers.begin();
for (; iter != m_observers.end(); ++iter )
{
// II. is static_cast the right way to go?
(*iter)(static_cast<T&>(*this));
}
}
};
对于问题1和问题2(在评论中)的任何帮助都将不胜感激。
I:我定义了struct TypeHelper,试图获得所需的成员指针类型。当类类型为模板化的m时,无法找到其他方法来完成此操作。
II:我如何强制MyClass中的模板类型匹配class Observed : public MyClass<Observed>
中继承的类型。最好的方法是什么?
这是一个可能的解决方案,对原始工作进行一些更改(使用禁用扩展的VC2010):
template <typename T>
class MyClass
{
private:
typedef std::function<void( T& )> CallbackFunction;
std::list< CallbackFunction > m_observers;
public:
virtual ~MyClass() {}
template<class M>
void AddObserver(M& observer, void typename (M::*callback)(T&))
{
CallbackFunction bound =
std::bind(callback, observer, std::placeholders::_1);
m_observers.push_back(bound);
}
protected:
void NotifyObservers()
{
std::list< CallbackFunction >::iterator iter = m_observers.begin();
for (; iter != m_observers.end(); ++iter )
{
(*iter)(static_cast<T&>(*this));
}
}
};
class Observed : public MyClass<Observed>
{
public:
void DoWork()
{
MyClass<Observed>::NotifyObservers();
}
};
class AnyObserver
{
public:
void HandleObserved(Observed&)
{
std::cout << "Observedn";
}
};
int main(int /*a_argc*/, char** /*a_argv*/)
{
AnyObserver any;
Observed observed;
observed.AddObserver(any, &AnyObserver::HandleObserved);
observed.DoWork();
return 0;
}
您可能需要在适当的地方重新添加tr1
名称空间。主要的变化是删除了TypeHelper
模板类。
对于static_cast
的使用,如果你确定你知道对象的类型是可以的。查看static_cast
和dynamic_cast
的详细答案。
如何强制MyClass中的模板类型与class> Observed: public MyClass中继承的类型匹配?最好的方法是什么?
一个可能的运行时解决方案是使用dynamic_cast
,因为如果强制转换无效,它将返回0:
void NotifyObservers()
{
std::list< CallbackFunction >::iterator iter = m_observers.begin();
for (; iter != m_observers.end(); ++iter )
{
T* t = dynamic_cast<T*>(this);
if (0 != t)
{
(*iter)(*t);
}
else
{
std::cerr << "Failed to castn";
}
}
}
如果定义了以下类, dynamic_cast
将返回0:
class XObserved : public MyClass<Observed>
{
public:
void DoWork()
{
MyClass<Observed>::NotifyObservers();
}
};
如何在MyClass中强制模板类型与类型匹配继承为观察类:公共MyClass。是什么最好的方法是什么?
这也可以在编译时完成。由Observer处理程序执行检查可能是最有意义的。在MyClass中添加一个处理程序可以检查的类型,比如DerivedType:
template <typename TT>
class MyClass
{
public:
typedef TT DerivedType;
};
template <typename AA, typename BB>
struct SameType;
template <typename AA>
struct SameType<AA, AA> {};
class AnyObserver
{
public:
template <typename VV>
void HandleObserved(VV&)
{
std::cout << "Observedn";
SameType<VV, VV::DerivedType>();
}
};
如果VV不是从MyClass派生的,那么HandleObserved()将编译失败,因为SameType只有在VV有一个类型DerivedType作为成员,并且VV和VV::DerivedType是相同类型时才会成功,这只有在VV派生自MyClass时才会发生。
class Derived: public MyClass<Derived>
{
};
class NotDerived
{
};
class Foo
{
};
class BadDerived1: public MyClass<Foo>
{
};
class BadDerived2: public MyClass<Derived>
{
};
和一个显示这些可观察对象代码的测试,导致编译时错误:
void test()
{
Derived foo; // ok
NotDerived bad1; // ok so far
BadDerived1 bar1; // ok so far
BadDerived2 bar2; // ok so far
AnyObserver obs;
obs.HandleObserved(foo); // ok
//obs.HandleObserved(bad1); // BANG! at compile time
//obs.HandleObserved(bar1); // BANG! at compile time
//obs.HandleObserved(bar2); // BANG! at compile time
}
我没有尝试VS2010,只有2005。
- 如何设计具有不同类型的通知和观察器的观察者模式?
- 反射 + 函数指针与观察者模式
- 观察者模式不起作用
- 观察者模式:为什么主题应该是抽象的?
- 观察者模式专业化
- 如何在不必绑定到特定类的情况下实现观察者模式
- C++,函数指针与观察者模式
- C++11观察者模式(信号、插槽、事件、更改广播器/侦听器,或任何您想称之为的东西)
- 实施观察者模式C
- C++自己的观察者模式
- 不同可观察量的观察者模式
- 通过Boost信号的观察者模式2
- 具有类型信息的观察者模式(C++)
- 代码设计:观察者模式
- 观察者模式和继承:未调用正确的函数
- C++和Qt:观察者模式错误
- 在C++中实现观察者模式
- C++ 观察者模式侦听器事件方法/类或信号和插槽
- 如何使用TR1实现观察者模式模板基类
- 通用主题类观察者模式