成员函数指针
class A{
public:
void Func(int){
std::cout << "I am in A" << std::endl;
}
};
void (A::*pFunc)(int) = &A::Func;
使用模板类
template <typename T>
class DelegateHandler{
public:
DelegateHandler(T *pT, void (T::*pFunc)(int)) : m_pT(pT),
m_pFunc(pFunc){}
void Invoke(int value){
(m_pT->*m_pFunc)(value);
}
private:
T *m_pT;
void (T::*m_pFunc)(int);
};
A a;
DelegateHandler<A> dha(&a, &A::Func);
dha.Invoke(3);
B b;
DelegateHandler<B> dhb(&b, &B::Method); //B::Method的声明与A::Func类似
dhb.Invoke(4);
到这里产生了一个问题:如果希望调用的目标是非成员函数,怎么办?上面的类模板无法调用非成员函数,不过使用模板偏特化就可以解决这个问题:
template<>
class DelegateHandler<void>{ //void代替前面的类型T,表示类模板没有参数
public:
DelegateHandler(void(*pFunc)(int)) : m_pFunc(pFunc){}
void Invoke(int value){
(*m_pFunc)(value);
}
private:
void(*m_pFunc)(int);
};
非成员函数的使用方法:
void NonmemberFunc(int param){
std::cout << "I am in NonmemberFunc!" << std::endl;
}
DelegateHandler<void> dhf(NonmemberFunc);
dhf.Invoke(5);
使用多态
对于单目标的委托来说,使用上面的代码或许就已经足够了。但是我的目的当然不止于此,我想要的是多目标的委托。多目标委托其实就是一个容器,在这个容器里可以存放多个对象(这里的对象指的是委托对象,不是A也不是B),当调用委托的时候依次调用每个对象。容器里的对象应该都是相同的类型,这样才能够放到强类型的容器中;而且委托调用方不应该知道具体的调用目标是什么,所以这些对象也应该要隐藏具体的细节。遗憾的是,上一步中实现的类模板都不具备这些能力,DelegateHandler和DelegateHandler是不同的类型,不能放到同一个容器中,调用方要调用它们也必须知道调用的目标是什么类型。
解决这个问题的方法就是使用多态,令所有的委托目标类都继承一个公共的接口,调用方只通过这个接口来进行调用,这样就不必知道每个目标(这里的目标还是指的委托)具体的类型。下面就是该接口的定义
class IDelegateHandler{
public:
virtual ~IDelegateHandler(){}
virtual void Invoke(int) = 0;
};
然后令DelegateHandler继承该接口:
template<typename T>
class DelegateHandler : public IDelegateHandler{
public:
DelegateHandler(T *pT, void (T::*pFunc)(int)) : m_pT(pT),
m_pFunc(pFunc){}
virtual void Invoke(int value) override {
(m_pT->*m_pFunc)(value);
}
private:
T *m_pT;
void (T::*m_pFunc)(int);
};
template<>
class DelegateHandler<void> : public IDelegateHandler{
public:
DelegateHandler(void (*pFunc)(int)) : m_pFunc(pFunc){}
virtual void Invoke(int value) override{
(*m_pFunc)(value);
}
private:
void (*m_pFunc)(int);
};
现在可以将各种类型的DelegateHandler放到同一个容器中,并使用同样的方式来调用了:
A a;
B b;
DelegateHandler<A> dha(&a, &A::*Func);
DelegateHandler<B> dhb(&b, &B::*Method);
DelegateHandler<void> dhf(NonmemberFunc);
std::vector<IDelegateHandler*> handlers;
handlers.push_back(&dha);
handlers.push_back(&dhb);
handlers.push_back(&dhf);
//这里的auto等于std::vector<IDelegateHandler*>::const_iterator
for (auto itor = handlers.cbegin(); itor != handlers.cend(); ++itor){
(*itor)->Invoke(7);
}