根据我发现的代码,似乎访问者需要知道访问对象的结构并调用所需的子代.在某些情况下,即使访问类被修改,访问者仍希望继续工作,这似乎有点笨拙.
我想真正的问题是:它们是一种模式,其中枚举是由访问过的代码而不是访问者代码完成的?
我有一个类应该为每个成员变量调用一个访问者方法.像这样的东西:
class A{
int a, b, c;
public:
void accept(Visitor &visitor){
visitor.visit(a);
visitor.visit(b);
visitor.visit(c);
}
};
Run Code Online (Sandbox Code Playgroud)
如何void accept() const在没有代码重复的情况下使用相同的代码获取方法?
重复的显而易见的解决方案是添加一个方法:
void accept(Visitor &visitor) const {
visitor.visit(a);
visitor.visit(b);
visitor.visit(c);
}
Run Code Online (Sandbox Code Playgroud)
该方法具有我想要的含义,但我想避免代码重复.拥有这两种方法的原因是能够通过"阅读"访问者读取变量并accept很好地使用该方法const.然后非const accept将可用于"写入/更新"访问者.
我有一个状态模式的实现,其中每个状态处理从事件队列获取的事件.State因此,基类具有纯虚方法void handleEvent(const Event*).事件继承基Event类,但每个事件都包含可以是不同类型的数据(例如int,string ......或者其他).handleEvent必须确定接收事件的运行时类型,然后执行向下转换以提取事件数据.事件是动态创建并存储在队列中的(因此在此处进行向上转换 ......).
我知道向下倾斜是一种糟糕设计的标志,但在这种情况下可以避免它吗?我正在考虑访问者模式,其中基类State将包含每个事件的虚拟处理程序,但是然后需要在代码片段中进行向下转换,该代码将队列中的事件从队列中取出并将其传递到当前状态.(至少在这种情况下,大switch(eventID)只会在一个地方......).访客模式是避免向下转换的最佳方式(最佳实践)吗?
这是伪代码(我boost::shared_ptr在这个例子中传递,但无论如何都会发生向下转换):
enum EventID
{
EVENT_1,
EVENT_2,
...
};
class Event
{
EventID id;
public:
Event(EventID id):id(id){}
EventID id() const {return id;}
virtual ~Event() = 0;
};
class Event1 : public Event
{
int n;
public:
Event1(int n):Event(EVENT_1), n(n){}
int getN() const {return n;}
};
class Event2 : public Event
{
std::string s; …Run Code Online (Sandbox Code Playgroud) 我在扩展应用程序时遇到了麻烦.这是一个考勤记录系统.目前,每位员工都通过具有QR码的卡记录出勤率.现在他们想要添加指纹识别,直到他们要求两种形式的识别必须在系统中共存时才会出现问题.因此,系统必须能够感知员工的QR,以及他的指纹.

通过.equalsTo(id)方法在QrIdStrategy中修复它的方法是:
equalsTo(id){
if (id == isKindOf (QrIdStrategy))
if (this.getEmployeeId () == id.getEmployeeId ())
return true;
return false;
}
Run Code Online (Sandbox Code Playgroud)
但我明白,询问一个对象的类是一个不好的做法,并不想这样做.我该如何解决?
我想到了访问者模式,但我仍然有同样的问题来比较两个不同类型的类(因为系统可以扫描这两种类型中的任何一种)

我是这种模式的新手,可以请别人帮助我吗?
我有一个像这样的对象:
public class Object
{
public string Name { get; set; }
public object Value { get; set; }
public List<Object> Childs { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是一个JSON示例:
{
"Name": "Method",
"Value": "And",
"Childs": [{
"Name": "Method",
"Value": "And",
"Childs": [{
"Name": "Operator",
"Value": "IsEqual",
"Childs": [{
"Name": "Name",
"Value": "5",
"Childs": []
}]
},
{
"Name": "Operator",
"Value": "IsEqual",
"Childs": [{
"Name": "Name",
"Value": "6",
"Childs": []
}]
}]
},
{
"Name": "Operator",
"Value": "IsEqual",
"Childs": [{
"Name": …Run Code Online (Sandbox Code Playgroud) 我们正在开发的软件系统需要在组件之间交换大量数据。数据的结构我们称之为变量树。这些数据本质上是组件之间的接口。代表特定接口的 C++ 代码是从接口描述自动生成的。进行实际数据交换有不同的底层实现,如 OPC/UA,但大部分代码都被屏蔽了。重要的节点类型是那些存储值和值数组的节点类型,它们几乎可以为任何类型实例化。
class node { /* whatever all nodes have in common */ };
class value_node : public node { /* polymorphic access to value */ };
template<typename T>
class typed_value_node : public value_node { /* type-safe access to value */ };
// imagine pretty much the same for array_node and typed_array_node
Run Code Online (Sandbox Code Playgroud)
因此,用于遍历这些树中节点的访问者基类具有接受所有整数类型(有符号和无符号)、所有浮点类型、布尔值和字符串的函数,无论是常量节点还是非常量节点。(我们目前计划将 enum 类型映射到 int/string 对,但对此没有一成不变的设置。)所有这些重载都存在于值和数组中。
目前,大约有 70 个重载:
class visitor {
public:
virtual ~visitor() = default;
virtual void accept( typed_value_node< char >&) = 0;
virtual …Run Code Online (Sandbox Code Playgroud) 如果我boost::variant支持的所有类型都使用相同的方法,那么有没有办法一般地调用它(即不为每个方法单独调用它static_visitor)?
我正试图让这样的东西起作用:
class A
{
void boo() {}
};
class B
{
void boo() {}
};
class C
{
void boo() {}
};
typedef boost::variant<A, B, C> X;
void foo(X& d)
{
x.boo();
}
Run Code Online (Sandbox Code Playgroud)
但它无法编译说'boo' : is not a member of 'boost::variant<T0_,T1,T2>'.
目前,我有一些类都继承自接口,因此可以多态地使用它们的单个共享方法.我还希望能够通过访问者使用这些类,因为所有其他方法对于每个具体类都是唯一的.我希望boost::variant可能是在这里实现我自己的访问者机制的更好的替代方案.是吗?
在C#中没有对变体类型(也称为标记的联合,区分联合)的直接支持.然而,人们可以使用访问者模式,通过双重调度实现歧视,并保证在编译时解决所有情况.然而,实施起来很繁琐.我想知道是否有更容易获得的方法:某种具有歧视机制的变体可以保证在C#的编译时解决所有联合的情况?
// This is a variant type. At each single time it can only hold one case (a value)
// from a predefined set of cases. All classes that implement this interface
// consitute the set of the valid cases of the variant. So at each time a variant can
// be an instance of one of the classes that implement this interface. In order to
// add a new case to the variant there …Run Code Online (Sandbox Code Playgroud) 我正在重写IR类和算法都在不断变化的编译器的IR。当前的编译器至少有2个当前IR,这些IR用于我要合并的不同阶段。
首先,我们有一个AST层次结构,它基于Node抽象基类和与其关联的访问者模式。接下来,我们有一个单独的语义层次结构,该层次结构使用了各种类(我可能可以全部重新设置基础,以便Node也是所有这些类的最低级别的类)。随着我们认识到更多的专业化,语义层次结构可能会增长。这些类有一个单独的Visitor模式。创建了2个“可执行” IR,用于执行生成的程序。
我的目标是合并AST和语义层次结构,并合并它们生成的可执行形式。这将减少由于两种形式的不一致导致的错误数量。
但是,正如我指出的那样,语义层次结构很可能会添加新的类。此外,我们也可能会添加新的访问者算法。
所以,我想做的是这样的:
class VisitorBase;
class Node;
template Visitable<T> {
virtual preVisitAccept(VisitorBase *v) {
v->preVisit(static_cast<T *>this); }
virtual inVisitAccept(VisitorBase *v) {
v->inVisit(static_cast<T *>this); }
virtual postVisitAccept(VisitorBase *v) {
v->postVisit(static_cast<T *>this); }
};
template Visitor<T> {
virtual preVisit(Node *n) { /* do nothing by default */ }
virtual inVisit(Node *n) { /* do nothing by default */ }
virtual postVisit(Node *n) { /* do nothing by default */ }
};
class VisitorBase : Visitor<VistorBase> {
};
class Node …Run Code Online (Sandbox Code Playgroud) 来自https://en.cppreference.com/w/cpp/utility/variant/visit:
visit?我不明白“访问者的选定调用”?示例代码
// Don't understand what this means, can explain? It's a templated func with trailing return type but no body?
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
// Why would the visitor function use && instead of &?
std::visit([](auto&& arg){std::cout << arg;}, v);
Run Code Online (Sandbox Code Playgroud)