c++ - 从父类的相同方法调用派生类方法
问题描述
我的问题如下:我正在编写服务器和客户端之间的可扩展通信协议。需要传输的对象使用命令设计模式。
这是课堂格式:
class command {
public:
using id = uint8_t;
using buffer = std::vector<char>;
enum command_t: id {a_command, another_command};
command() = delete;
command(id id): id_(id) {}
static command* unserialize(buffer);
virtual buffer const serialize() const = 0;
virtual void execute() = 0;
protected:
/* Not possible, see further where I explain. Keeping it here for
my example */
virtual static command* do_unserialize(buffer::iterator, buffer::iterator) = 0;
id id_;
};
class a_command;
class another_command;
每个命令都将是command
. id将command_t
与每个命令相关联。在上面的示例中,a_command
并且another_command
也将具有相应的类。
command::serialize
在派生类中实现。它所做的是将类的所有需要的信息写入字节数组并返回。当然,受保护的情况也是如此command::do_unserialize
——它需要一个字节数组并将其转换为正确类型的命令。但问题是:
缓冲区的第一个字节总是与command::id
好的子类相关联。当服务器/客户端接收数据时,它将读取命令 ID,然后需要能够将其反序列化为正确的命令类型。这就是为什么它需要调用静态函数command::unserialize
而不是子类之一的原因do_unserialize
。
一个快速而肮脏的修复将是command::unserialize
这样的:
command* command::unserialize(buffer b) {
auto it{b.begin()};
command::id const id{*it++};
switch(static_cast<command::command_t>(id)) {
case command::command_t::a_command:
return a_command::do_unserialize(it, b.end());
case command::command_t::another_command:
return another_command::do_unserialize(it, b.end());
default:
throw std::invalid_argument("command::unserialize: unknown command ID");
}
}
*** 实际上甚至没有,你不能有一个虚拟的静态成员函数。所以我不知道它是如何实现的。
即使它有效,它也不是很有趣,因为它意味着必须为每个创建的新命令复制一行代码。
编辑:一个工作示例是移动do_unserialize
到子类构造函数并返回指向新创建对象的指针。
class derived_command: public command {
public:
derived_command(buffer::iterator beg, buffer::iterator end) {
// do_unserialize logic
}
};
// unserialize
switch (id) {
case command::command_t::derived_class: return new derived_class(b.begin(), b.end());
}
// ...
因此,我的问题是这样的:有没有办法只从command::id
现场动态链接新命令?一种从其 ID 推断要使用的子类的方法?否则,我的设计有缺陷吗?有没有更好的方法来做我想做的事情?
谢谢!
解决方案
推荐阅读
- c++ - 为什么这个 constexpr if 不能编译
- ruby-on-rails - 胭脂宝石最小示例未显示格式?
- php - 未找到使用 Web 中间件的 Laravel API 路由
- c - 存在链接和符号时的“未定义引用”
- reactjs - react+spring boot 开发设置
- json - 如何使用 f# 反序列化 json 以获得正确的类型
- node.js - 如何使用 Nodejs 对从 mongoDB 获取的数据求和
- c# - 如何将任何类型的值传递给函数
- c - 从比特流中提取 10 位字
- angular - “错误错误:未捕获(承诺中):InvalidValueError:不是 LatLngBounds 或 LatLngBoundsLiteral:不是对象”页面加载时使用