类和类间成员函数指针



我想创建一个通用环缓冲类,用于获取不同类型的连接(uart,can等)。问题在于不同的命令类型/样式等。所以我决定只使用指针(我的意思是数字,而不是c指针)在环缓冲区中工作,并从它调用属于不同连接类型的函数。

所以我创建了这个类和typedef函数指针:

typedef bool(*bufCommandProcessor)(uint8_t pointer);
class rbuf
{
uint8_t bufsize;
uint8_t psize;
uint8_t readPointer;
uint8_t writePointer;
bufCommandProcessor processPut;
bufCommandProcessor processRead;
public:
rbuf();
rbuf(uint8_t bsize, bufCommandProcessor putpr, bufCommandProcessor readpr);
uint8_t cyclicPlus(uint8_t num, uint8_t maxval);
bool checkEmpty();
bool checkFull();
bool putCommand();
bool readCommand();
};

,这里是其中的put/read命令

bool rbuf::putCommand() 
{
if (checkFull()) 
{
readPointer = cyclicPlus(readPointer, psize);
this->processPut(writePointer % bufsize);
writePointer = cyclicPlus(writePointer, psize);
}
else {
this->processPut(writePointer % bufsize);
writePointer = cyclicPlus(writePointer, psize);
}
return true;
}

bool rbuf::readCommand() 
{
if (checkEmpty()) {
return false;
}
this->processRead(readPointer % bufsize);
readPointer = cyclicPlus(readPointer, psize);
return true;
}

和(我在Visual Studio中测试逻辑,所以我使用一些只在桌面上有意义的命令)我创建了一个测试UART类:

typedef bool(*putcmd)();
class UART 
{
uint8_t RingBuffer[BUFSIZE][STRINGSIZE] {};
uint8_t Command[STRINGSIZE];
uint8_t Len;
putcmd uput;
UART();
UART(putcmd cput);
void cmdcm(uint8_t* cmd, uint8_t len);
bool uartRBput(uint8_t wp);
bool uartRBget(uint8_t rp);
};

和它的命令是:

UART::UART(putcmd cput) 
{
Command[0] = 0;
Len = 0;
RingBuffer[0][0] = 0;
uput = cput;
}
void UART::cmdcm(uint8_t* cmd, uint8_t len)
{
Len = len;
memcpy(Command, cmd, Len);
memset(&Command[Len], 0, STRINGSIZE-Len);
uput();
}
bool UART::uartRBput(uint8_t wp)
{
memcpy(RingBuffer[wp], Command, STRINGSIZE);
return true;
}

我想创建它的实例,比如

UART uart;
rbuf uartRB(BUFSIZE, uart.uartRBput, uart.uartRBget);
uart = UART(rbuf.putCommand);
作为一个想法,似乎很好,但我不知道如何实现它。这可能吗?

这可能吗?

有办法解决这个问题。正如@Someprogrammerdude在评论中指出的那样,您可以使用std::functionstd::bind和lambdas。

注意bufCommandProcessorputcmd是普通的函数指针,不能与成员函数指针一起工作。

解决方案是std::function和一些类型擦除器开销。例如,通过lambdas函数或std::bind_front(自c++20起)包装要调用的实例及其成员函数,可以这样做:

rbufclass:

// type aliases for callable function object
using bufCommandProcessor = std::function<bool(uint8_t)>;
class rbuf
{
// ....
bufCommandProcessor processPut;
bufCommandProcessor processRead;
public:
rbuf() {}
rbuf(uint8_t bsize, bufCommandProcessor putpr, bufCommandProcessor readpr)
: processPut{ putpr }
, processRead{ readpr }
{}
// ...
};

UART

// type aliases for callable function object
using putcmd = std::function<bool()>;
class UART 
{
// ...
std::function<bool()> uput;
public:
UART() = default;
UART(putcmd cput)
: uput{ cput }
{}
// ...
};

现在在调用方

UART uart;
rbuf uartRB{ 10u
, [uart](uint8_t wp) mutable { return uart.uartRBput(wp); }
, [uart](uint8_t rp) mutable { return uart.uartRBget(rp); }
};
// alternatively using std::bind_front
uart = UART{ std::bind_front(&rbuf::putCommand, uartRB) };

(参见示例)

最新更新