访客:通过继承添加更多类型

发布于 2024-11-15 08:58:54 字数 2070 浏览 6 评论 0原文

我想通过继承扩展已声明的访问者,并让运行时环境搜索访问者的后代以获取要执行的正确方法。我可以在 C# 中使用它,但我希望在 C++ 中使用它。我在 g++ 中尝试了以下代码,但未调用派生方法;仅调用基类的方法。

#include <iostream>
using namespace std;

struct Field; // Forward declaration

struct Visitor
{
    virtual void visit(Field& f) = 0; // Visits Field objecs and objects derived from Field.
};

struct Field_String;

struct Visitor_Field_String : public Visitor
{
    // Extend the Visitor by specifying a visitation
    //     for Field_String
    virtual void visit(Field_String& fs) = 0;
};

struct Field
{
    void accept_visitor(Visitor& v)
    {
        cout << "Field accepting visitor.\n";
        v.visit(*this);
    }
};

struct Field_String : public Field
{
    void accept_visitor(Visitor& v)
    {
        cout << "Field_String accepting visitor.\n";
        v.visit(*this);  // Line 1
    }
};

struct Full_Visitor : Visitor_Field_String
{
    void visit(Field& f)
    {
        cout << "Visiting a Field object\n";
        return;
    }
    void visit(Field_String& fs)
    {
        cout << " Visiting a Field_String object\n";
        return;
    }
};


int main(void)
{
    Field_String fs;
    Full_Visitor visitor;
    fs.accept_visitor(visitor);
    return 0;
}

我得到以下输出:

# g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# g++ -o virtual_visitor.exe virtual_visitor.cpp
# ./virtual_visitor.exe
Field_String accepting visitor.
Visiting a Field object

我想要的输出是:

Field_String accepting visitor.
Visiting a Field_String object

我的两个问题:

  1. 为什么 visit 方法在 后裔访客没有被处决?
  2. 如何执行 visit 方法 在后代访客中使用 多态性?

注意:目标是通过使用继承并允许可能不使用 Visitor 中指定的所有类的情况来减少 Visitor 类中指定的类。

注意:这是不是双重调度,而是延长调度。

I want to expand a declared Visitor through inheritance and have the run-time environment search the descendents of the Visitor for the correct method to execute. I can have this in C#, but I'm looking to use it in C++. I tried the following code in g++ and the descendent method is not called; only the method for the base class is called.

#include <iostream>
using namespace std;

struct Field; // Forward declaration

struct Visitor
{
    virtual void visit(Field& f) = 0; // Visits Field objecs and objects derived from Field.
};

struct Field_String;

struct Visitor_Field_String : public Visitor
{
    // Extend the Visitor by specifying a visitation
    //     for Field_String
    virtual void visit(Field_String& fs) = 0;
};

struct Field
{
    void accept_visitor(Visitor& v)
    {
        cout << "Field accepting visitor.\n";
        v.visit(*this);
    }
};

struct Field_String : public Field
{
    void accept_visitor(Visitor& v)
    {
        cout << "Field_String accepting visitor.\n";
        v.visit(*this);  // Line 1
    }
};

struct Full_Visitor : Visitor_Field_String
{
    void visit(Field& f)
    {
        cout << "Visiting a Field object\n";
        return;
    }
    void visit(Field_String& fs)
    {
        cout << " Visiting a Field_String object\n";
        return;
    }
};


int main(void)
{
    Field_String fs;
    Full_Visitor visitor;
    fs.accept_visitor(visitor);
    return 0;
}

I get the following output:

# g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# g++ -o virtual_visitor.exe virtual_visitor.cpp
# ./virtual_visitor.exe
Field_String accepting visitor.
Visiting a Field object

The output I want is:

Field_String accepting visitor.
Visiting a Field_String object

My two questions:

  1. Why is the visit method in the
    descendent Visitor not executed?
  2. How do I execute the visit method
    in the descendent Visitor using
    polymorphism?

Note: The objective is to reduce the classes specified in a Visitor class, by using inheritance and allowing for the cases that may not use all of the classes specified in the Visitor.

Note: This is not double dispatch, but extended dispatch.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

熊抱啵儿 2024-11-22 08:58:54

你不能在 C++ 中做到这一点(你真的可以在 C# 中做到这一点吗?)关于特定问题:

  1. 编译器根据引用的静态类型和该函数的最终重写者解析要使用的函数重载基于对象的动态类型。

  2. 您需要在基类中提供所有不同的重载。如果你做不到,你可以做一些令人讨厌的事情,比如dynamic_cast来尝试确定收到的Visitor是否支持该特定字段,但我会避免这样做所有费用。
    调度*。

由于不同的字段类型没有被多态地使用(或者至少看起来不像,因为 accept_visitor 函数不是虚拟的),为什么不接受具体的访问者类型?

struct Field_String : Field
{
    void accept_visitor(Visitor_Field_String& v)
    {
        cout << "Field_String accepting visitor.\n";
        v.visit(*this);
    }
};

You cannot do that in C++ (can you really do it in C# without reflection?) On the particular questions:

  1. The compiler resolves the function overload to use based on the static type of the reference, and the final overrider of that function based on the dynamic type of the object.

  2. You need to provide all of the different overloads in the base class. If you cannot do it, you can do nasty things like dynamic_cast's to try and determine whether the Visitor received has support for that particular field, but I would avoid it at all costs.
    dispatch*.

Since the different field types are not being used polymorphically (or at least it does not seem like it, since the accept_visitor functions are not virtual), why don't you accept the concrete visitor type?

struct Field_String : Field
{
    void accept_visitor(Visitor_Field_String& v)
    {
        cout << "Field_String accepting visitor.\n";
        v.visit(*this);
    }
};
够运 2024-11-22 08:58:54

您是否有理由必须从 Visitor 虚拟类派生第二个 Visitor_Field_String 虚拟类类型?例如,如果您像这样定义基本 VisitorFull_Visitor 类:

struct Visitor
{
    virtual void visit(Field& f) = 0;
    virtual void visit(Field_String& fs) = 0;
};

struct Full_Visitor : public Visitor
{
    void visit(Field& f)
    {
        cout << "Visiting a Field object\n";
        return;
    }
    void visit(Field_String& fs)
    {
        cout << " Visiting a Field_String object\n";
        return;
    }
};

您将获得您正在寻找的功能。您想要做的问题是 fs.accept_visitor(visitor) 被多态转换为的类类型是 Visitor 对象类型,仅定义了virtual void Visit(Field& f)。因此,在 Visitor 类型的类上调用 visit(),无需对 内的 Visitor_Field_String 类类型进行某种类型的额外转换Accept_visitor() 函数不会引用 visit() 函数的其他重载版本,因为它们是在派生类中定义的。

Is there a reason you have to derive a second Visitor_Field_String virtual class type from you Visitor virtual class? For instance, if you define your base Visitor and Full_Visitor classes like this:

struct Visitor
{
    virtual void visit(Field& f) = 0;
    virtual void visit(Field_String& fs) = 0;
};

struct Full_Visitor : public Visitor
{
    void visit(Field& f)
    {
        cout << "Visiting a Field object\n";
        return;
    }
    void visit(Field_String& fs)
    {
        cout << " Visiting a Field_String object\n";
        return;
    }
};

you'll get the functionality you're looking for. The problem with what you're trying to-do is that the class-type that fs.accept_visitor(visitor) is being polymorphically cast to is a Visitor object-type which only has virtual void visit(Field& f) defined. So calling visit() on a class of type Visitor, without some type of additional cast to a Visitor_Field_String class-type inside your accept_visitor() functions will not refer to the additional overloaded versions of your visit() function as they're defined in the derived class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文