有没有人知道如何在C中正确处理双重调度而不使用RTTI和dynamic_cast<>还有一个解决方案,其中类层次结构是可扩展的,即基类可以从进一步派生,它的定义/实现不需要知道它?
我怀疑没有办法,但我很高兴被证明是错的:)
我怀疑没有办法,但我很高兴被证明是错的:)
解决方法
要实现的第一件事是双重(或更高阶)调度不能扩展.单身
dispatch和n类型,你需要n个函数;用于双重发送n ^ 2,依此类推.你怎么
处理此问题部分决定了您如何处理双重调度.一个明显的解决方案是
通过创建一个封闭的层次结构来限制派生类型的数量;在这种情况下,双重发送可以
使用访客模式的变体轻松实现.如果不关闭层次结构,
那么你有几种可能的方法.
dispatch和n类型,你需要n个函数;用于双重发送n ^ 2,依此类推.你怎么
处理此问题部分决定了您如何处理双重调度.一个明显的解决方案是
通过创建一个封闭的层次结构来限制派生类型的数量;在这种情况下,双重发送可以
使用访客模式的变体轻松实现.如果不关闭层次结构,
那么你有几种可能的方法.
如果你坚持认为每一对都对应一个函数,那么你基本上需要一个:
std::map<std::pair<std::type_index,std::type_index>,void (*)(Base const& lhs,Base const& rhs)> dispatchMap;
(根据需要调整函数签名.)您还必须实现n ^ 2函数,和
将它们插入dispatchMap. (我假设你使用免费功能;没有
将它们放入其中一个类而不是另一个类的逻辑原因.)之后,您调用:
(*dispatchMap[std::make_pair( std::type_index( typeid( obj1 ) ),std::type_index( typeid( obj2 ) )])( obj1,obj2 );
(你显然想把它包装成一个函数;它不是你想分散的东西
遍布代码.)
一个小变体就是说只有某些组合是合法的.在这种情况下,您可以使用
在dispatchMap上找到,如果找不到要查找的内容,则会生成错误.
(期待很多错误.)如果您可以定义某种默认值,则可以使用相同的解决方案
行为.
如果你想100%正确地完成它,一些函数能够处理中间类
和它的所有衍生物,你需要某种更动态的搜索,并订购
控制重载分辨率.考虑例如:
Base / \ / \ I1 I2 / \ / \ / \ / \ D1a D1b D2a D2b
如果你有f(I1,D2a)和f(D1a,I2),应选择哪一个.最简单的解决方案
只是一个线性搜索,选择可以调用的第一个(由dynamic_cast确定)
指向对象的指针),并手动管理插入顺序以定义重载
你希望的决议.但是,使用n ^ 2个函数,这可能会很快变慢.以来
有一个排序,应该可以使用std :: map,但是排序函数会去
实际上是非常重要的(并且仍然必须在整个过程中使用dynamic_cast)
地点).
考虑到所有事情,我的建议是将双重调度限制在小的,封闭的层次结构中,并坚持访客模式的一些变体.