委托简单的理解就是把函数(成员函数、全局函数或静态函数)指针封装成一个仿函数类,
这样做的好处有:
1、解耦函数实现和调用(函数的调用者不知道函数的实现者)
2、加强类型安全性(函数指针是一个内存指针,委托是一个类)
3、作为参数传递(替换回调函数)
c++ 标准库并没有实现委托的功能,C++98/03 实现起来比较困难(可以参考fastDelegate),C++11之后有了可变模板参数后,实现起来相对容易了,以下是C++11实现委托的代码:
#pragma once
/**********************************
* file: delegate.h
* author: vison0300@163.com
* date:2018-11-23
**********************************/
namespace dlgt
{
template<typename TReturn, typename...TArgs>
class TDelegate
{
typedef TReturn return_type;
struct IBaseFunction
{
virtual return_type operator()(TArgs... args) = 0;
};
template <typename TClass>
class TMemberFunction : public IBaseFunction
{
public:
typedef TClass class_type;
typedef return_type(class_type::*function_type)(TArgs...);
explicit TMemberFunction(class_type* pObj, function_type pFunc)
{
m_pObj = pObj;
m_pFunc = pFunc;
}
virtual return_type operator()(TArgs... args)
{
return (m_pObj->*m_pFunc)(args...);
}
private:
class_type* m_pObj;
function_type m_pFunc;
};
class CStaticFunction : public IBaseFunction
{
public:
typedef return_type(*function_type)(TArgs...);
explicit CStaticFunction(function_type pFunc)
{
m_pFunc = pFunc;
}
virtual return_type operator()(TArgs... args)
{
return (*m_pFunc)(args...);
}
public:
function_type m_pFunc;
};
IBaseFunction* m_pBaseFunc;
void clear()
{
if (m_pBaseFunc)
{
delete m_pBaseFunc;
m_pBaseFunc = nullptr;
}
}
public:
TDelegate()
{
m_pBaseFunc = nullptr;
}
template<typename TClass>
explicit TDelegate(TClass* pObj, typename TMemberFunction<TClass>::function_type pFunc)
{
bind(pObj, pFunc);
}
explicit TDelegate(typename CStaticFunction::function_type pFunc)
{
bind(pFunc);
}
~TDelegate()
{
clear();
}
template<typename TClass>
void bind(TClass* pObj, typename TMemberFunction<TClass>::function_type pFunc)
{
clear();
m_pBaseFunc = new TMemberFunction<TClass>(pObj, pFunc);
}
void bind(typename CStaticFunction::function_type pFunc)
{
clear();
m_pBaseFunc = new CStaticFunction(pFunc);
}
return_type operator()(TArgs... args)
{
return (*m_pBaseFunc)(args...);
}
};
}
测试代码:
#include <iostream>
#include "delegate.h"
class CMath
{
public:
int Add(int a, int b)
{
std::cout << "CMath::Add(" << a << "," << b << ") = " << a + b << "\r\n";
return a + b;
}
void Test()
{
std::cout << "CMath::Test()" << "\r\n";
}
};
int add(int a, int b)
{
std::cout << "add(" << a << "," << b << ") = " << a + b << "\r\n";
return a + b;
}
int main()
{
dlgt::TDelegate<int, int, int> d1(add);
d1(1, 2);
CMath m;
d1.bind(&m, &CMath::Add);
d1(3, 4);
dlgt::TDelegate<void> d2(&m, &CMath::Test);
d2();
getchar();
return 0;
}
输出结果: