是否可以使用包含{sub,super}类函数指针的回调表

Is it possible to use a callback table which contains {sub,super}class function pointers?

本文关键字:类函数 指针 回调 super 可以使 包含 sub 是否      更新时间:2023-10-16

i当前有一个连接对象,该连接对象可以为传入命令请求执行处理。每个命令是使用无序地图映射到回调方法的字符串。一个修剪的示例,说明了核心函数:

#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。但是,很快就显而易见的是,在处理人员之间有足够的重叠,为两者创建一个共同的类是有意义的。

我想创建一个包含Connmgmt和Conndata共享功能的连接库。

我的问题与回调功能表有关。

我想有一个表来将命令请求字符串映射到回调函数,我希望方法指针能够参考派生类中的方法。IE。我有一个针对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();
}

此代码以多种方式被打破,但我特别想知道是否:

  • 拥有" Connmgmt :: Handlers"表的想法是否包含Connbase和Connmgmt中的方法的指示?编译器croaks,说指针是错误的类型。
  • 如果有一种方法可以解决问题,我是否会进入不确定的行为(或更糟(的领域?我已经读到,可以使用方法指针类型进行子类"应该",但是有与虚拟类有关的警告(并且在此注:中是 em 虚拟函数,但是
  • 都没有处理程序功能。
  • 给定我想完成的工作(创建一个弦到方法调度程序,该方法可能驻留在不同的类中(尽管始终属于同一类层次结构((,是否有一些惯用的C 17?

(不允许提升(。

您可以通过一些更改来完成您需要的事情。

如果将ProcFn的类型更改为

typedef void (ConnMgmt::*ProcFn)();

然后,您几乎可以准备构建ConnMgmt::handlers表。您需要指定std::pair的类型。然后剩下的问题是ConnBase::proc_ping受到保护,无法访问。修复的方法是将参考更改为 ConnMgmt::proc_ping

const std :: unordered_map connmgmt :: handlers = { std :: pair(" ping",&amp; connmgmt :: proc_ping(, std :: pair(" create_user",&amp; connmgmt :: proc_create_user(};

每个派生的类都需要自己的处理程序表和ProcFn Typedefs。