gpt4 book ai didi

C++ 访问者模式和多态性

转载 作者:行者123 更新时间:2023-11-30 05:24:08 25 4
gpt4 key购买 nike

以下代码是我在我的项目中实现的 VisitorPattern 的简化版本。

#include <iostream>
class AVisitor {
public:
virtual void visit(class A *) = 0;
};

class ExtendedVisitor : public AVisitor {
public:
virtual void visit(class B *) = 0;
};

class A {
public:
virtual void accept(AVisitor *visitor) {
std::cout << "Call accept of A" << std::endl;
visitor->visit(this);
}
};

class B : public A {
public:
void accept(AVisitor *visitor) override {
std::cout << "Call accept of B" << std::endl;
B *just_this = this;
visitor->visit(just_this); //why this calls to visit(A*)
visitor->visit((B*) just_this); //useless casting
}
};

class ActualVisitor : public ExtendedVisitor {
public:
void visit(A *x) override {
std::cout << "Call visit on A*" << std::endl;
}
void visit(B *x) override {
std::cout << "Never called" << std::endl;
}
};

int main() {
ActualVisitor visitor;
A *a = new B();
a->accept(&visitor);
}

我不明白为什么B类的accept方法调用的是visitor(A*)方法而不是visitor(B*)方法。主要功能打印

Call accept of B
Call visit on A*
Call visit on A*

相反,以下代码的行为符合我的预期:

#include <iostream>

class AVisitor {
public:
virtual void visit(class A *) = 0;
virtual void visit(class B *) = 0;
};

class A {
public:
virtual void accept(AVisitor *visitor) {
std::cout << "Call accept of A" << std::endl;
visitor->visit(this);
}
};

class B : public A {
public:
void accept(AVisitor *visitor) override {
std::cout << "Call accept of B" << std::endl;
B *just_this = this;
visitor->visit(just_this); //now it works
visitor->visit((B*) just_this);
}
};

class ActualVisitor : public AVisitor {
public:
void visit(A *x) override {
std::cout << "Call visit on A*" << std::endl;
}
void visit(B *x) override {
std::cout << "Call visit on B*" << std::endl;
}
};

int main() {
ActualVisitor visitor;
A *a = new B();
a->accept(&visitor);
}

它现在打印:

Call accept of B
Call visit on B*
Call visit on B*

问题似乎是 AVisitor 类的继承问题。我想知道为什么会发生这种情况以及设计具有“专门”访问者的 VisitorPattern 的正确方法是什么(这里 ExtendedVisitor 也可以访问 B 对象)

最佳答案

您的 B::accept 具有以下签名:

void accept(AVisitor *visitor) override;

那么,让我们检查一下AVisitor 的接口(interface)。它有

virtual void visit(class A *) = 0;

这就是它的全部(在您的第一个版本中)。 ExtendedVisitor 确实有

virtual void visit(class B *) = 0;

但是不会覆盖AVisitor 中的方法。事实上,您的第二个版本可以帮助您了解原因。由于

virtual void visit(class A *) = 0;
virtual void visit(class B *) = 0;

可以一起驻留在同一个类中(它们在您的第二个版本中是重载),那么在这方面它们是不同的方法。

关于C++ 访问者模式和多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38811377/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com