访问者模式是区分 C++ 中参数类型的最快方法吗?
访问者模式是 C++ 中完成方法参数类型识别(有效地对参数而不是成员类进行单次分派)的最快方法吗?我可能知道我想要对尚不知道的子类型的元素调用的确切方法,因此总是在 中进行额外的虚拟方法调用,例如
是不可取的。V::visit(A *)
>A::accept(V &v) { v.visit(this); }
// Is the Visitor pattern recommended here? (E inherits D inherits B.)
class Foo {
public:
virtual void visit(B *) { result = 3; }
virtual void visit(D *) { result = 4; }
virtual void visit(E *) { result = 5; }
private:
int result;
}; // class Foo
// Need to add generic interface to B and its children ...
class B {
public:
virtual void accept(class Foo &f) { f.visit(this); }
}; // class B
我想要功能上等同于以下但具有 O(1) 成本的东西,据我所知,这对于dynamic_cast<>是不可能的。或 typeid() 梯子,因为 std::type_info
不能是 constexpr/switchable。
// O(n) search cost might get nasty with bigger hierarchies.
int foo(B *b) {
if (typeid(b) == typeid(B *)) { return 1; }
if (typeid(b) == typeid(D *)) { return 2; }
if (typeid(b) == typeid(E *)) { return 3; }
return -1;
}
我在这里有什么选择?感谢您的建议!
编辑:更改了示例代码以通过字段提供结果,这样不同的方法类型就不需要多个签名。谢谢,莫里斯!
最终决定:除了不喜欢访问者模式的强制双重调度成本之外,我还想避免重载 foo()
带来的接口膨胀,但我不这样做不要认为有一个已知的干净模式可以做到这一点。我最终只是做了直接的静态重载,然后就到此为止了。无论如何,我想要将重载封装在函数内最多可能是一个值得怀疑的目标。谢谢莫里斯的回复。
Is the Visitor Pattern the fastest way to accomplish method parameter type identification (effectively single dispatch on a parameter, not a member's class) in C++? I might know the exact method(s) I want to invoke on elements of not-yet-know subtype, so invariably making an additional virtual method call like V::visit(A *)
in A::accept(V &v) { v.visit(this); }
is undesirable.
// Is the Visitor pattern recommended here? (E inherits D inherits B.)
class Foo {
public:
virtual void visit(B *) { result = 3; }
virtual void visit(D *) { result = 4; }
virtual void visit(E *) { result = 5; }
private:
int result;
}; // class Foo
// Need to add generic interface to B and its children ...
class B {
public:
virtual void accept(class Foo &f) { f.visit(this); }
}; // class B
I'd like something functionally equivalent the following but with O(1) cost, which is AFAIK not possible with dynamic_cast<> or typeid() ladders, since std::type_info
can't be a constexpr/switchable.
// O(n) search cost might get nasty with bigger hierarchies.
int foo(B *b) {
if (typeid(b) == typeid(B *)) { return 1; }
if (typeid(b) == typeid(D *)) { return 2; }
if (typeid(b) == typeid(E *)) { return 3; }
return -1;
}
What are my options here? Thanks for the advice!
Edit: Changed sample code to feed results through field, such that multiple signatures aren't needed for different method types. Thanks, Maurice!
Final decision: In addition to not liking the mandatory double dispatch cost of the Visitor Pattern, I also wanted to avoid the interface bloat of overloading foo()
, but I don't think that there is a known clean pattern to do this. I ended up just doing straight static overloads and called it a day. Anyway, my wanting to encapsulate overloading inside a function is probably a questionable goal at best. Thanks, Maurice for the response.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
事实上,接口不需要重复。访问者的子类可以处理操作的细节。在您的情况下:
因此,每个类中只需要一个accept() 方法。
我能想到的访问者模式的所有替代方案都涉及某种运行时搜索,所以是的,恕我直言,访问者模式是最快的方法。
In fact, the interfaces need not be duplicated. The subclasses of the visitor can handle the details of the operation. In your case:
So, only one accept() method is needed in each class.
All the alternatives to the visitor pattern I can think of involve some kind of run-time searching, so yes, IMHO, the visitor pattern is the fastest way.