c++ RTTI注册模式
C++ RTTI Registry Pattern
我有兴趣了解更多关于c++中RTTI的优点和局限性。假设我有以下场景:
class C {};
class C0 : public C {};
class C1 : public C {};
...
void print(int id, C* c) {
if (id == 0) dynamic_cast<C0 *>(c)->print();
else if (id == 1) dynamic_cast<C0 *>(c)->print();
...
}
是否有可能使用注册表模式实现上面的示例?例如,使用这样的代码:
map<int, ?> registry;
void print(int id, C* c) {
registry[id](c)->print();
}
这很容易通过使print
成为虚函数来解决。然后你可以简单地输入:
void print(C* c)
{
c->print();
}
,它会为所有的派生类做正确的事情。
但是如果你想保持print
非虚拟,那么你就会意识到registry[id](c)->print();
这样的东西是如何工作的。映射的值类型是编译时的事实,但您希望运行时的行为有所不同。
好吧,我可以想到一个方法……通过使用虚函数。您需要创建一个类,作为C
的包装器,其派生版本与从C
派生的类型匹配。使用一些模板可能会使这个问题更容易处理。然后,根据指向基类的指针声明映射,但通过派生包装器填充映射。
print
本身设置为虚拟所能实现的更多的好处。虽然使用多态性和虚拟方法似乎更合适,但您可以使用以下内容来根据id
class PrintCaller
{
public:
template <typename T>
std::size_t register_class()
{
m.push_back([](C* c) {
auto* p = dynamic_cast<T*>(c);
if (p) {
p->print();
} else {
throw std::runtime_error("Incorrect type");
}
});
return m.size() - 1;
}
void print(std::size_t id, C* c) const {
if (id < m.size()) {
m[id](c);
} else {
throw std::runtime_error("invalid id");
}
}
private:
std::vector<std::function<void(C*)>> m;
};
生活例子
相关文章:
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 无法将结构注册为增强几何体3D点
- 为什么在保护模式下继承升级不起作用
- 如何在全屏模式下(在OpenGL中)使背景透明
- 如何使用AngelScript注册SFML Vector2运算符
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 此模式的C++RegEx
- avrogencpp能为模式中的每种类型生成单独的头文件吗
- 使用可变模板的Broadcaster/Listener模式
- c++方法参数只能在linux的发布模式下自行更改
- 在遍历处理程序的向量时注册和注销处理程序
- 有没有任务栏API可以立即应用注册表更改
- 如何应用注册表模式使"select class depend on input"遵守开放封闭原则?
- ActiveX OCX可以在释放模式内置时注册,但不能在调试模式下注册
- 在Qt中注册元类型的模式
- c++工厂模式使用模板进行自注册
- c++装饰器模式,带有模板的静态多态性和注册回调方法
- c++ RTTI注册模式
- 设计模式——在c++中,当实现(一组单例)直接从它们的编译单元在某个注册表中自注册时,它被称为什么?