C ++:对访问者模式有疑问 [英] C++: doubts about visitor pattern

查看:154
本文介绍了C ++:对访问者模式有疑问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道Visitor Pattern是什么以及如何使用它;此问题不是此一个的重复。 p>




我有一个库,我把大多数可重用的代码写入,我链接到我的大多数项目。



通常我需要向某些类添加功能,但是不会将这些新功能添加到库中。让我使用一个真实的例子:



在这个lib中,我有一个类 Shape c $ c> CircleShape , PolygonShape CompositeShape



我现在开发一个图形应用程序,我需要渲染这些 Shape ,但不想放一个虚函数<$ c因为我的一些项目使用 Shape Shape 类中的$ c> render >不做任何渲染,其他图形项目可以使用不同的渲染引擎(我使用Qt这个项目,但对于一个游戏,我会使用OpenGL,因此 render function需要不同的实现)。



当然,最有名的方法是使用Visitor Pattern,但这会在我的脑海中引起一些疑惑:



任何类的任何类库都需要扩展为 Shape 。大多数公共图书馆(大约所有公共图书馆)不提供任何对游客模式的支持;为什么?为什么要这样?



访问者模式是一种在C ++中模拟双重调度的方法。它不是C ++中的本机,需要显式实现,使类接口更复杂:我不认为 applyVisitor 函数应该在我的类的同一级别



显式地展开 Shape with dynamic_cast 更贵,但对我来说,它看起来像一个更清洁的解决方案。






我该怎么办?在我的所有库类中实现双重调度?如果提供 Shape 的库不是我的,但是在互联网上找到了一些GPL库?

解决方案

首先:访问者模式是一种在C ++中模拟双重调度的方式。 实际上,双调度是多调度的一种形式,这是一种在C ++中模拟(缺少)多方法的方法。






类层次结构上的操作是否应通过添加虚函数 / strong>或添加访问者 取决于添加类与添加操作的概率:




  • 如果 类数量持续更改 的速度比操作数量更快, 使用虚函数强>。这是因为添加类需要修改所有访问者。

  • 如果 类数量相对稳定 ,与操作次数相比, em> 。这是因为添加虚拟函数需要更改层次结构中的所有类。



是的,许多库没有访问者界面。

当我们只是看看推理上面,如果类的数量经常变化,这将是正确的。也就是说,如果一个库经常被释放,新的类被不断地添加,那么提供一个访问接口将没什么意义,因为每次新版本带来新类时,使用库的每个人都需要适应所有的访问者。所以如果我们只看上面的推理,访问者界面似乎只有在一个lib的类层次结构中的类的数量很少或从不改变。



但是,对于第三方库,还有另一个方面:通常,用户不能更改库中的类。也就是说,如果他们需要添加操作, 如果库提供了钩子,他们唯一可以做的是添加访问者 -

如果您正在编写图书馆,并希望用户能够向其中添加操作,则 需要提供一种方式让他们将访问者插入您的lib


I know what Visitor Pattern is and how to use it; this question is not a duplicate of this one.


I've got a library where I put most of the reusable code I write, and which I link to most of my projects.

Often I need to add features to some classes, but without adding these new features to the library. Let me use a real example:

In this lib I've got a class Shape, inherited by CircleShape, PolygonShape and CompositeShape.

I'm now developing a graphical application where I need to render these Shape, but don't want to put a virtual function render in the core Shape class, since some of my projects which use Shape don't do any rendering, and other graphical projects could use different rendering engines (I'm using Qt for this project, but for a game I'd use OpenGL, thus the render function will need different implementations).

The most famous way to do this is using Visitor Pattern, of course, but this pops a few doubts into my mind:

Any class of any library could need to be extended as my Shape does. Most of the public libraries (about all of them) don't provide any support for Visitor Pattern; why? why should I?

Visitor Pattern is a way to simulate Double Dispatching in C++. It's not native in C++, and requires to be explicitly implemented, making the class interface more complex: I don't think the applyVisitor function should be at the same level of my class' functions, I see this like breaking abstraction.

Explicitly up-casting Shape with dynamic_cast is more expensive, but to me it looks like a cleaner solution.


So, what should I do? Implementing Double Dispatching in all my library classes? What if the library providing Shape wasn't mine, but some GPL library found on the internet?

解决方案

First: "Visitor Pattern is a way to simulate Double Dispatching in C++." This is, erm, not fully right. Actually, double dispatch is one form of multiple dispatch, which is a way to simulate (the missing) multi-methods in C++.


Whether operations on a class hierarchy should be implemented by adding virtual functions or by adding visitors is determined by the probabilities of adding classes vs. adding operations:

  • If the number of classes keeps changing more rapidly than the number of operations, use virtual functions. That is because adding a class requires modifying all visitors.
  • If the number of classes is relatively stable compared to the number of operations, use visitors. That is because adding a virtual function requires changing all classes in the hierarchy.

Yes, many libraries do not come with a visitor interface.
When we are just looking at the reasoning above, this would be right if the number of classes changes often. That is, if a library is released often, with new classes being added constantly, then providing a visitor interface wouldn't make much sense, because each time a new release brings new classes, everybody using the library need to adapt all of their visitors. So if we only looked at the above reasoning, a visitor interface would seem to only be helpful if the number of classes in a lib's class hierarchy seldom or never changes.

However, with 3rd-party libraries there's another aspect to that: Usually, users cannot change the classes in the library. That is, if they need to add an operation, the only way they can do this is by adding a visitor - if the library provides the hooks for them to plug into it.
So if you are writing a library and feel like users should be able to add operations to it, then you need to provide a way for them to plug their visitors into your lib.

这篇关于C ++:对访问者模式有疑问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆