我知道什么是访客模式以及如何使用它。这个问题不是one的重复。

我有一个库,其中存放了我编写的大部分可重复使用的代码,并链接到了我的大多数项目。

通常,我需要向某些类中添加功能,而无需向库中添加这些新功能。让我用一个真实的例子:

在这个库中,我有一个Shape类,它由CircleShapePolygonShapeCompositeShape继承。

我现在正在开发一个图形应用程序,在其中我需要呈现这些Shape,但是不想在核心render类中放置虚拟函数Shape,因为我的一些使用Shape的项目都不会进行任何渲染,而其他项目图形项目可以使用不同的渲染引擎(我在该项目中使用Qt,但对于游戏,我将使用OpenGL,因此render函数将需要不同的实现)。

当然,最著名的方法是使用“访客模式”,但这使我有些疑惑:

像我的Shape一样,任何库的任何类都可能需要扩展。大多数公共(public)图书馆(大约所有公共(public)图书馆)都没有为“访客模式”提供任何支持;为什么?我为什么要?

访客模式是一种在C++中模拟Double Dispatching的方法。它不是C++的 native ,需要显式实现,从而使类接口(interface)更加复杂:我不认为applyVisitor函数不应与类函数处于同一级别,我认为这类似于破坏抽象。

Shape显式上载dynamic_cast更昂贵,但对我来说,这似乎是一种更干净的解决方案。

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

最佳答案

第一:“访问者模式是在C++中模拟Double Dispatching的一种方式。”嗯,这不是完全正确的。实际上,双重调度是多重调度的一种形式,这是一种在C++中模拟(缺失)多种方法的方法。

是通过添加虚拟函数或通过添加访客的来实现对类层次结构的操作,这取决于添加类与添加操作的可能性:

  • 如果类的数量使的更改比操作数更快地更改,则使用虚拟函数。那是因为添加一个类需要修改所有访问者。
  • 如果与操作数量相比,类的数量相对稳定,则使用访问者。这是因为添加虚拟函数需要更改层次结构中的所有类。

  • 是的,许多图书馆没有访问者界面。
    当我们只看上面的推理时,如果类的数量经常变化,这将是正确的。也就是说,如果一个库经常发布,并且不断添加新类,那么提供访问者接口(interface)就没有多大意义,因为每次新版本带来新类时,每个使用该库的人都需要适应所有访问者。因此,如果我们仅看上述推理,那么访问者界面似乎仅在lib的类层次结构中的类数很少或从不更改的情况下才有用。

    但是,对于第三方库,还有另一个方面:通常,用户无法更改库中的类。也就是说,如果他们需要添加操作,唯一的方法是通过添加访问者-,前提是该库提供了供他们插入的 Hook
    因此,如果您正在编写一个库,并且觉得用户应该能够向其中添加操作,那么您需要提供一种方法,让他们将其访问者插入您的lib 中。

    10-08 20:02
    查看更多