Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 更通用的访问者模式_C++_Design Patterns_Visitors - Fatal编程技术网

C++ 更通用的访问者模式

C++ 更通用的访问者模式,c++,design-patterns,visitors,C++,Design Patterns,Visitors,我很抱歉,如果我的问题是这么长和技术,但我认为它是如此重要,其他人会对此感兴趣 我在寻找一种方法,将一些软件的内部结构与它们在c语言中的表示清楚地分开++ 我有一个泛型参数类(稍后存储在容器中),它可以包含boost::any类中的任何类型的值 我有一个这样的基类(大致上)(当然还有更多的东西) 当然,除非我使用RTTI或自己实现它(使用enum和switch case),否则我无法从中理解真正的参数类型,但您知道,这不是正确的OOP设计解决方案 经典的解决方案是访问者设计模式 这种模式的问题是

我很抱歉,如果我的问题是这么长和技术,但我认为它是如此重要,其他人会对此感兴趣

我在寻找一种方法,将一些软件的内部结构与它们在c语言中的表示清楚地分开++

我有一个泛型参数类(稍后存储在容器中),它可以包含boost::any类中的任何类型的值

我有一个这样的基类(大致上)(当然还有更多的东西)

当然,除非我使用RTTI或自己实现它(使用enum和switch case),否则我无法从中理解真正的参数类型,但您知道,这不是正确的OOP设计解决方案

经典的解决方案是访问者设计模式

这种模式的问题是,我必须提前知道将实现哪些派生类型,因此(将wikipedia中编写的内容和我的代码放在一起)我们将有:

struct Visitor 
{
  virtual void visit(ParameterLimitedInt& wheel) = 0;
  virtual void visit(ParameterAnyInt& engine) = 0;
  virtual void visit(ParameterFilename& body) = 0;
};
是否有任何解决方案可以通过任何其他方式获得这种行为,而无需事先了解所有具体类型,也无需获得原始访客


编辑:,但问题仍然是一样的,该方法实际上依赖于动态强制转换,我试图将其作为一种(即使很弱)RTTI方法来避免

也许最好是考虑一些解决方案,甚至不引用访客模式,并清理我们的头脑。其目的只是具有以下功能:

Widget* CreateWidget(const Parameter& p)

如果我理解正确,每个“具体”参数的行为会有所不同,而不会丢失其类型的信息


我们有一个可以使用不同硬件选项的对象。为了实现这一点,我们使用了设备的抽象接口。这个设备有一系列的功能,可以在某些事件中触发。使用方法相同,但设备的各种实现要么具有完全充实的功能,要么立即返回。为了让生活更轻松,函数是无效的,当出现问题时会抛出异常。

我使用了(“非循环访问者”)以获得良好的效果;在某种程度上,它可以在不改变现有类的情况下向层次结构中添加新类。

为了完整起见:

当然,完全可以为对象编写自己的多方法指针表实现,并在运行时手动计算方法地址。在实现多方法(尽管是在编译器中)这一主题上,有一个由Stroustup提出的问题


我真的不会建议任何人这样做。让实现运行良好是相当复杂的,使用它的语法可能会非常笨拙且容易出错。如果其他一切都失败了,这可能仍然是一条路。

我很难理解您的要求。但是,用我自己的话来说,我所理解的情况是这样的:

  • 您有一个抽象的参数类,它最终被子类化为一些具体的类(例如:ParameterLimitedInt)

  • 您有一个单独的GUI系统,它将以通用方式传递这些参数,但关键是它需要呈现特定于参数类的具体类型的GUI组件

  • 限制是您不想执行RTTID,也不想编写代码来处理每种可能的具体参数类型

  • 您可以使用访问者模式

鉴于这些是您的要求,我将如何处理这种情况:

我将实现访问者模式,其中accept()返回一个布尔值。基参数类将实现一个virtual accept()函数并返回false

参数类的具体实现将包含accept()函数,这些函数将调用访问者的visit()。他们会回到现实

visitor类将使用模板化的visit()函数,因此您将只覆盖您希望支持的具体参数类型:

class Visitor
{
public:
  template< class T > void visit( const T& param ) const
  {
    assert( false && "this parameter type not specialised in the visitor" );
  }
  void visit( const ParameterLimitedInt& ) const; // specialised implementations...
}
类访问者
{
公众:
模板<类别T>无效访问(常量T和参数)常量
{
断言(false&“此参数类型不专门用于访问者”);
}
void visit(const参数limitedint&)const;//专门的实现。。。
}
因此,如果accept()返回false,您就知道该参数的具体类型尚未实现访问者模式(如果有其他逻辑,您更愿意根据具体情况处理)。如果访问者模式中的assert()被触发,那是因为它没有访问您已经实现了专门化的参数类型


所有这一切的一个缺点是,不受支持的访问只在运行时被捕获。

对于一个通用的实现,我建议,这篇文章的一部分。

这篇文章似乎消失了,真是太遗憾了:它激起了我的兴趣。我想八年在互联网上是永恒的。@Nicole
Widget* CreateWidget(const Parameter& p)
class Visitor
{
public:
  template< class T > void visit( const T& param ) const
  {
    assert( false && "this parameter type not specialised in the visitor" );
  }
  void visit( const ParameterLimitedInt& ) const; // specialised implementations...
}