bind重载的类的非静态成员

头文件

#include <functional>

实现

// 实现一个通用的apdu准备的函数,通过调用p方法来实现协议的wrap和发送
// 方法 p 来将 apdu 打包为[head][apdu][tail]
// 这里我们想让 protocolUse 是一个函数指针
template<typename protocolUse,typename flagType>

void packDlmsHandAndSend(Meter* mtr,CGXDLMSSecureClient& gx,DLMS_COMMAND type,protocolUse p,flagType flag)
{
    p(mtr, bufout[0],flag);
}

一个类想调用这个方法

// 类自身的底层包装,发送函数,即 protocolUse
int IEC46::sendToMeter(void)
{
    return  0;
}

int IEC46::sendToMeter(Meter *meter, CGXByteBuffer &subGxData, IEC46::comTypeEnum flag)
{
    return  sendToMeter(meter, Buffer(subGxData.GetData(), subGxData.GetSize()), flag);
}

// 这个是函数的类型,注意这里不能使用 mm来取代Fun
// bind 的返回是 function 不是简单的函数指针 
// typedef int (*mm)(Meter *meter, CGXByteBuffer &subGxData, IEC46::comTypeEnum flag);

typedef std::function<int (Meter *meter, CGXByteBuffer &subGxData, IEC46::comTypeEnum flag)> Fun;
using mysend = int(IEC46::*)(Meter *meter, CGXByteBuffer &subGxData, IEC46::comTypeEnum flag);

// 1. 绑定一个函数,这里可以直接使用auto bindFunc2
// 这里的类型声明 mysend 不可省略,因为有重载的同名成员函数,如果没有同名的,可以省略
Fun bindFunc2 = std::bind((mysend)&IEC46::sendToMeter,this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3);
// 2. 调用形式可以省略掉 <Fun,IEC46::comTypeEnum>
packDlmsHandAndSend<Fun,IEC46::comTypeEnum>(mtr,gxClient,DLMS_COMMAND_DISCONNECT_REQUEST,bindFunc2,comTask);


//3. 精简的形式可以如下:
using mysend = int(IEC46::*)(Meter *meter, CGXByteBuffer &subGxData, IEC46::comTypeEnum flag);
auto bindFunc2 = std::bind((mysend)&IEC46::sendToMeter,this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3);
packDlmsHandAndSend(mtr,gxClient,DLMS_COMMAND_DISCONNECT_REQUEST,bindFunc2,comTask);


简单一点的形式

其实在这里,我们可以直接传递类为模版到packDlmsHandAndSend,然后调用p.sendToMeter(xxx)

iec46下的成员函数,调用
	makeApdu(type,sendByIec46)	 发送数据
更理想的应该是

iec46类下面有个发送函数,调用 makeApdu ,最终发送数据
posted @ 2020-10-15 20:46  zongzi10010  阅读(129)  评论(0编辑  收藏  举报