C++ 访客模式如何避免沮丧

C++ 访客模式如何避免沮丧,c++,visitor,C++,Visitor,任何人都可以在前后显示示例代码以避免访问者模式代码的降级吗 谢谢 该示例使用双重分派,没有向下投射。一个简单的、最低限度的示例 之前 这就是框架。现在实现实际的访问者以多态方式处理对象 // Implementing custom visitor class Printer : public Visitor { virtual void Visit(Derived1& d1) { std::printf("Handling Derived1\n"); }

任何人都可以在前后显示示例代码以避免访问者模式代码的降级吗


谢谢

该示例使用双重分派,没有向下投射。

一个简单的、最低限度的示例

之前 这就是框架。现在实现实际的访问者以多态方式处理对象

// Implementing custom visitor
class Printer : public Visitor {
    virtual void Visit(Derived1& d1) { std::printf("Handling Derived1\n"); }
    virtual void Visit(Derived2& d2) { std::printf("Handling Derived2\n"); }
};

// Some arbitrary function that handles Base.
void
Handle(Base& obj)
{
    Printer p;
    obj.Accept(p);
}
  • Accept()
    是一个虚拟函数,它以
    obj
    的类型进行调度(首次调度)
  • 然后调用适当的重载
    Visit()
    ,因为在
    Accept()
    中,您已经知道对象的类型
  • Visit()

  • 因为您有双重分派(一个在对象上,另一个在访问者上),所以您不进行任何铸造。缺点是,任何时候向层次结构添加类时,都必须更新访问者类,以添加适当的函数来处理新的子类。

    我理解您的解释,但我想知道在示例中应用访问者模式之前,类层次结构的用途是什么。我想知道handle方法是在基类还是派生类中。派生类实现的典型示例是什么?@peterwkc,我添加了类层次结构。它完全一样,除了没有访客位
    Handle()
    只是一个任意函数,它可以运行到任何地方(无论在哪里)。作为层次结构一部分的派生类必须实现
    Accept()
    ,并自己调用访问者。最后一点不是缺点,而是优点。在编译时被迫更新访问者类通常比跟踪几十条if-else语句的向下转换要好。
    // Class definitions
    class Visitor;
    class Base {
    public:
        // This is for dispatching on Base's concrete type.
        virtual void Accept(Visitor& v) = 0;
    };
    class Derived1 : public Base {
    public:
        // Any derived class that wants to participate in double dispatch
        // with visitor needs to override this function.
        virtual void Accept(Visitor& v);
    };
    class Derived2 : public Base {
    public:
        virtual void Accept(Visitor& v);
    };
    class Visitor {
    public:
        // These are for dispatching on visitor's type.
        virtual void Visit(Derived1& d1) = 0;
        virtual void Visit(Derived2& d2) = 0;
    };
    
    // Implementation.
    void
    Derived1::Accept(Visitor& v) {
        v.Visit(*this); // Calls Derived1 overload on visitor
    }
    void
    Derived2::Accept(Visitor& v) {
        v.Visit(*this); // Calls Derived2 overload on visitor
    }
    
    // Implementing custom visitor
    class Printer : public Visitor {
        virtual void Visit(Derived1& d1) { std::printf("Handling Derived1\n"); }
        virtual void Visit(Derived2& d2) { std::printf("Handling Derived2\n"); }
    };
    
    // Some arbitrary function that handles Base.
    void
    Handle(Base& obj)
    {
        Printer p;
        obj.Accept(p);
    }