我目前有一个连接对象,该对象执行传入命令请求的处理。每个命令都是一个字符串,该字符串使用无序映射映射到回调方法。精简示例说明了核心功能:
#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>
class Conn;
typedef void (Conn::*ProcFn)();
class Conn
{
private:
void proc_ping();
static const std::unordered_map<std::string, ProcFn> handlers;
public:
void simulate();
};
const std::unordered_map<std::string, ProcFn> Conn::handlers = {
std::pair("ping", &Conn::proc_ping)
};
void Conn::proc_ping()
{
std::cout << "ping!" << std::endl;
}
void Conn::simulate()
{
auto pfn = handlers.at("ping");
std::invoke(pfn, this);
}
int main()
{
Conn c;
c.simulate();
}
这很好,但我意识到我需要多个具有不同主要角色的网络接口(认为“管理接口”与“客户端数据接口”),因此我将Conn类的副本复制到ConnMgmt和ConnData中。但是,很快就发现处理程序之间有足够的重叠,因此有必要为两者创建一个通用类。
我要创建一个ConnBase,其中包含ConnMgmt和ConnData的共享功能。
我的问题与回调函数表有关。
我希望有一个表将命令请求字符串映射到回调函数,但是我希望方法指针能够引用派生类中的方法。即我有一个ConnBase和ConnMgmt或ConnBase和ConnData的调度程序(取决于要调用的接口)。
这是[非功能性]代码,它说明了我要完成的工作的要点:
#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>
class ConnBase;
typedef void (ConnBase::*ProcFn)();
class ConnBase
{
protected:
void proc_ping();
};
void ConnBase::proc_ping()
{
std::cout << "ping!" << std::endl;
}
class ConnMgmt : public ConnBase
{
protected:
static const std::unordered_map<std::string, ProcFn> handlers;
void proc_create_user();
public:
void simulate();
};
void ConnMgmt::proc_create_user()
{
std::cout << "create user!" << std::endl;
}
const std::unordered_map<std::string, ProcFn> ConnMgmt::handlers = {
std::pair("ping", &ConnBase::proc_ping),
std::pair("create_user", &ConnMgmt::proc_create_user)
};
void ConnMgmt::simulate()
{
auto pfn = handlers.at("ping");
std::invoke(pfn, this);
pfn = handlers.at("create_user");
std::invoke(pfn, this);
}
int main()
{
ConnMgmt c;
c.simulate();
}
此代码以多种方式被破坏,但是我特别想知道是否:
(不允许提升)。
答案 0 :(得分:1)
只需进行一些更改即可完成所需的操作。
如果将ProcFn
的类型更改为
typedef void (ConnMgmt::*ProcFn)();
然后,您几乎准备好构建ConnMgmt::handlers
表。您需要指定std::pair
的类型。然后剩下的问题是ConnBase::proc_ping
受保护,并且不可访问。解决该问题的方法是将引用更改为ConnMgmt::proc_ping
。
const std :: unordered_map ConnMgmt :: handlers = { std :: pair(“ ping”,&ConnMgmt :: proc_ping), std :: pair(“ create_user”,&ConnMgmt :: proc_create_user) };
每个派生类将需要自己的处理程序表和ProcFn
typedef。