指向成员函数 C++ 的指针
Pointer to member function C++
我是 C++ 的新手,我在使用指向成员函数的指针函数时遇到问题。我正在 ESP8266 上使用 PlatformIO 编程。
UdpTask.h
class UdpTask : public Task {
public:
void setup();
void loop();
UdpTask(String (*handleGson)(String));
private:
char replyPacket[];
char incomingPacket[UDP_TX_PACKET_MAX_SIZE];
unsigned int localUdpPort;
WiFiUDP Udp;
String (*handleGson)(String);
};
UdpTask.cpp
UdpTask::UdpTask(String(*handleGson)(String)) {
this->handleGson = handleGson;
}
GsonHandler.h
class GsonHandler {
public:
String handleGson(String gson);
};
GsonHandler.cpp
String GsonHandler::handleGson(String gson) {
return ":)";
}
main.cpp
GsonHandler gsonHandler;
UdpTask udpTask(&gsonHandler.handleGson);
错误:
src\main.cpp:16:30: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say '&GsonHandler::handleGson' [-fpermissive]
UdpTask udpTask(&gsonHandler.handleGson);
^
src\main.cpp:16:40: error: no matching function for call to 'UdpTask::UdpTask(String (GsonHandler::*)(String))'
UdpTask udpTask(&gsonHandler.handleGson);
注:
我已经尝试了错误消息中的建议,但我找不到让它工作的方法......此外,我知道在这个简单的例子中它可以更容易地解决,例如只传递整个对象,但我再次需要这种指针,因为这种方式更容易。
提前致谢。
As it was pointed out already in the comments - the argument that UdpTask(String (*handleGson)(String));
constructor expects is not a pointer to a member function. Rather it is a pointer to a free function. A pointer to a member function would be of the form:
String (GsonHandler::*)(String)
Note that pointer to a member need to know a member of what type it is.
As to your original problem - there are a number of ways to solve it (as always the case with C++).
Most straightforward is to use std::function<String(String)>
to store a functor
. That is any object that can be called. So something like:
class UdpTask : public Task {
public:
UdpTask(std::function<String(String)> f);
private:
...
std::function<String(String)> handler;
};
In the implementation, you just call it as: handler(args);
In case you can not use std
function - other solutions can be explored.
Simplest would be to store a pointer to a handler in you UdpTask
and call its method directly:
class UdpTask : public Task {
public:
UdpTask(GsonHandler* handler);
private:
...
GsonHandler* handler;
};
In the implementation, you just call it as: handler->handleGson(args);
Now, I do recognise that there might be arcitual concerns about tight coupling between UdpTask
and what is eccentially a UDP data handler
.
So you may consideg making generic interface for DataHandler, storing pointer to it and making GsonHandler
an implementation of DataHandler
:
struct DataHandler {
virtual ~DataHandler() = default;
virtual String handleData(String data) = 0;
};
struct GsonHandler: public DataHandler {
String handleData(String data) override;
...
};
...
class UdpTask : public Task {
public:
UdpTask(DataHandler* handler);
private:
...
DataHandler* handler;
};
我是 C++ 的新手,我在使用指向成员函数的指针函数时遇到问题。我正在 ESP8266 上使用 PlatformIO 编程。
UdpTask.h
class UdpTask : public Task {
public:
void setup();
void loop();
UdpTask(String (*handleGson)(String));
private:
char replyPacket[];
char incomingPacket[UDP_TX_PACKET_MAX_SIZE];
unsigned int localUdpPort;
WiFiUDP Udp;
String (*handleGson)(String);
};
UdpTask.cpp
UdpTask::UdpTask(String(*handleGson)(String)) {
this->handleGson = handleGson;
}
GsonHandler.h
class GsonHandler {
public:
String handleGson(String gson);
};
GsonHandler.cpp
String GsonHandler::handleGson(String gson) {
return ":)";
}
main.cpp
GsonHandler gsonHandler;
UdpTask udpTask(&gsonHandler.handleGson);
错误:
src\main.cpp:16:30: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say '&GsonHandler::handleGson' [-fpermissive]
UdpTask udpTask(&gsonHandler.handleGson);
^
src\main.cpp:16:40: error: no matching function for call to 'UdpTask::UdpTask(String (GsonHandler::*)(String))'
UdpTask udpTask(&gsonHandler.handleGson);
注: 我已经尝试了错误消息中的建议,但我找不到让它工作的方法......此外,我知道在这个简单的例子中它可以更容易地解决,例如只传递整个对象,但我再次需要这种指针,因为这种方式更容易。
提前致谢。
As it was pointed out already in the comments - the argument that UdpTask(String (*handleGson)(String));
constructor expects is not a pointer to a member function. Rather it is a pointer to a free function. A pointer to a member function would be of the form:
String (GsonHandler::*)(String)
Note that pointer to a member need to know a member of what type it is.
As to your original problem - there are a number of ways to solve it (as always the case with C++).
Most straightforward is to use std::function<String(String)>
to store a functor
. That is any object that can be called. So something like:
class UdpTask : public Task {
public:
UdpTask(std::function<String(String)> f);
private:
...
std::function<String(String)> handler;
};
In the implementation, you just call it as: handler(args);
In case you can not use std
function - other solutions can be explored.
Simplest would be to store a pointer to a handler in you UdpTask
and call its method directly:
class UdpTask : public Task {
public:
UdpTask(GsonHandler* handler);
private:
...
GsonHandler* handler;
};
In the implementation, you just call it as: handler->handleGson(args);
Now, I do recognise that there might be arcitual concerns about tight coupling between UdpTask
and what is eccentially a UDP data handler
.
So you may consideg making generic interface for DataHandler, storing pointer to it and making GsonHandler
an implementation of DataHandler
:
struct DataHandler {
virtual ~DataHandler() = default;
virtual String handleData(String data) = 0;
};
struct GsonHandler: public DataHandler {
String handleData(String data) override;
...
};
...
class UdpTask : public Task {
public:
UdpTask(DataHandler* handler);
private:
...
DataHandler* handler;
};