Modern C++ Design 笔记 第十一章 MultiMethods(1)

如果说前面我们已经把武功练到了第十重境界的话,最后一章意味着我们马上要打开任督二脉,一夜飞升了:)基于这样的关键的时间点,我们愿意非常谨慎的把这个问题分三次慢慢的讲,讲清楚。这第一次我们将说到这个MultiMethod话题的开始和第一个解决方案。

这个MultiMethod的问题源自于C++不支持多参数的函数多态,(其实原先我不觉得我们有这么多这样类型的需求,但是当看到不知道起什么名字的时候我相信了)而且恰好这里的需求和Alex的Sample惊人的类似。这里我们不再对问题本身做过多的描述,而是直奔主题的寻求第一个最直观的解决方案。

这个方案被命名为The Brute-Force,其实就是Dynamic_cast的反复使用从而确定具体的类型是什么,到确定类型以后,直接调用对应类型的子函数,下面我们展示一下最原始的实现代码:

看到这样的代码很多人的第一反应就是disgusting,这样的代码对于任何一个需要维护的程序员来说都是噩梦。当然这个时代需要大师帮主我们把这些东西掩盖起来,提供给我们更为优雅的实现。如果我们还记得递归之美的TypeList的话,这一切都讲变得豁然开朗。如果编译器可以帮我们把这些IF-ELSE隐藏在TypeList的递归里面可能这样的方案在某种程度上仍然是个不错的主意,让这样设计从模板参数开始,我们需要的参数大概是这样的:

这里包括了executor(就是那个拥有一组类似接口的类),baseLhs就是第一参数的基类,TypesLhs就是第一参数的list,相同的后面有第二参数的基类的list,最有一个就是ResultType做返回值。一样的,我们还是做匹配,比如对于第一个参数我们有这样的搜寻方式:

如果是head*,那么就处理第二参数,如果不是,就从这里lhs里面继续遍历。可以想见的是对于第二参数rhs,我们采用了相同的方式,只是优点在于,代码优雅了不少。对任何一个维护着来说,也不需要在多加那些新加入类的处理。紧接着这里,我们贴出整个一个完整的StaticDispatcher的实现:

看到了这个完整的实现,我们需要补充说几点:

1. 递归总是要收敛的,所以不管DispatchRhs还是DispatchLhs都会对NullType有一个偏特化的的OnError处理。这要求我们在这个Executor里面有一个onError的实现。

2. 我们注意到这里还有一个bool symmetric = true,的申明。从名字我们可以知道这是一个关于对称性的开关,比较自然的。如果有两个参数Rectangle&和Poly&,不管先后我都最好可以调用func(Rectangle&, Poly&)或者func(Poly&,Rectangle&)。所以这里的Traits帮了我们的忙,注意这里的IndexOf依赖于lhs和rhs的顺序问题。还有这里在搜寻lhs和rhs的时候其实都是没有确定第一参数或者第二参数的。这里的DispatchLhs或者DispatchRhs只是确定这些rhs和lhs在baselist里面是存在的!所以这样对称性的讨论感觉还是在两个list的元素相同的情况下讨论比较有意义。

3. 还有一个问题就是TypeList里面的顺利问题,这个问题有点想catch exception的顺序问题,如果基类在前,那么那些派生类就没有机会被访问到了。TYPELIST_4(Rectangle, Ellipse, Poly, RoundedRectangle)如果是这样的一个申明,每次的RoundedRectangle&的类型在Rectangle&做dynamic_cast都成功的阻截了。所以你应该或者在申明的时候谨慎的手动组织好继承关系,或者用第三章的DeriveToFront让编译器帮你组织。

总的来看,其实这样优雅的实现还没有改变想法本身,依然是匹配。根据变量的实际类型来匹配对应的函数,应该说在类结构比较简单的时候比较好用,也比较迅速。但是当类型比较复杂的时候,就不是那么实际。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值