在访问者模式的典型实现中,类必须考虑基类的所有变体(后代).在许多情况下,访问者中的相同方法内容应用于不同的方法.在这种情况下,模板化的虚拟方法将是理想的,但目前,这是不允许的.
鉴于(基础):
struct Visitor_Base; // Forward declaration.
struct Base
{
virtual accept_visitor(Visitor_Base& visitor) = 0;
};
// More forward declarations
struct Base_Int;
struct Base_Long;
struct Base_Short;
struct Base_UInt;
struct Base_ULong;
struct Base_UShort;
struct Visitor_Base
{
virtual void operator()(Base_Int& b) = 0;
virtual void operator()(Base_Long& b) = 0;
virtual void operator()(Base_Short& b) = 0;
virtual void operator()(Base_UInt& b) = 0;
virtual void operator()(Base_ULong& b) = 0;
virtual void operator()(Base_UShort& b) = 0;
};
struct Base_Int : public Base …Run Code Online (Sandbox Code Playgroud) c++ templates virtual-functions operator-overloading visitor
你知道一个好的java对象图访问者库吗?
我想访问一个对象及其子组件,并在匹配某些条件时执行一些操作.
用法示例:
nullSet的TreeSet实例替换每个.我想要一个库,而不是自定义代码,因为遍历一个Object图可能很棘手.你必须处理集合,数组,代理等...我已经考虑过重用XStream的一部分来实现这一点,但它看起来并不那么容易:Xstream访问者更倾向于对象转换而不是对象自我修改.
我想这个问题或它的变化会传递很多,所以如果我说的是重复的,答案在其他地方,请通知我.
我一直在研究游戏引擎设计,并且遇到了基于组件的实体模型.这听起来很有希望,但我仍在努力实施它.
我正在考虑一个系统,其中引擎安排了几个"子系统",它管理一些方面,如渲染,声音,健康,AI等.每个子系统都有一个与之关联的组件类型,就像健康的健康组件子系统."实体",例如NPC,门,某些视觉效果或播放器,简单地由一个或多个组件组成,这些组件一起为实体提供其功能.
我确定了四个主要的信息传递渠道:一个组件可以广播到其当前实体中的所有组件,一个组件可以广播到其子系统,一个子系统可以广播到其组件,一个子系统可以广播到其他子系统.
例如,如果用户想要移动他们的角色,他们会按一个键.此按键将由输入子系统拾取,然后输入子系统广播该事件并由播放器子系统拾取.然后,播放器子系统将此事件发送给所有播放器组件(以及这些组件组成的实体),并且这些播放器组件将与其自己的实体的位置组件通信以继续并移动.
所有这一切对于一个关键的新闻似乎有点啰嗦,我当然愿意改进这种架构.但无论如何,我的主要问题仍然存在.
至于事件本身,我考虑了事件在访客模式中的行为.我想要的重要性是,如果一个事件遇到它不支持的组件(因为在移动事件中没有与AI或健康直接相关),它将忽略该组件.如果一个事件没有找到它正在追踪的组件,那就没关系了.
访客模式几乎可行.但是,它需要我为每种类型的组件(即visitHealthComponent,visitPositionComponent等)提供虚函数,即使它与它们没有任何关系.我可以将这些函数留空(所以如果遇到这些函数,它会被忽略),但每次添加一个组件时我都要添加另一个函数.
我希望能够添加一个组件而不必将东西添加到其他地方,并添加一个事件而不会弄乱其他东西.
那么,我的两个问题:
在这个问题中,据说我可以使用访客模式而不是一堆instanceofs.Jmg说:"如果你不能自由改变A,B和C,你可以应用访客模式来实现同样的目标."
据我所知,我仍然需要为A,B和C支持访问者(accept()例如,有一个方法).
我的问题是我完全没有可能改变A,B和C.我只是从外国图书馆获得Car对象并且必须调用wash()特定于卡车,赛车和公共汽车的方法.
我想我还需要一个if-else-if带instanceofs 的结构.我对吗?
我正在尝试将AST与ANTLR4一起使用,包含以下文件:
Builder.java
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.TokenStream;
public class Builder
{
public static void main(String[] args)
{
CharStream input = new ANTLRInputStream("ON M1==2 && M3 == 5 && (M2 > 1 || M5 <= 5.0) "
+ "DO P5:42 P4:10");
ExprLexer lexer = new ExprLexer(input);
TokenStream tokens = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokens);
parser.addParseListener(new ExprTestListener());
ExprParser.ExpressionContext uu = parser.expression();
}
}
Run Code Online (Sandbox Code Playgroud)
ExprTestListener:
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.antlr.v4.runtime.tree.ErrorNode;
public class ExprTestListener extends ExprBaseListener …Run Code Online (Sandbox Code Playgroud) 关于树的访问者模式,我遇到了代码重复问题.目前的情况如下:我有一棵树,由两个不同的节点类组成,即叶子和非叶子.另外,我有两个看起来非常相似的访客基类,除了一个访问const树和其他非const树.具体访问者必须执行的实际操作与节点的具体类型无关.我举一个简短的例子:
class Visitor;
class ConstVisitor;
class Node {
public:
virtual void accept(Visitor&) = 0;
virtual void accept(ConstVisitor&) const = 0;
};
class Leaf : public Node {
virtual void accept(Visitor& v) {v.visitLeaf(*this);}
virtual void accept(ConstVisitor& cv) {cv.visitLeaf(*this);}
};
class CompoundNode : public Node {
public:
vector<Node*> getChildren() const;
virtual void accept(Visitor& v) {v.visitCompoundNode(*this);}
virtual void accept(ConstVisitor& cv) {cv.visitCompoundNode(*this);}
};
class Visitor {
protected:
virtual void processNode(Node& node) = 0;
public:
void visitLeaf(Leaf& leaf) {
processNode(leaf);
}
void visitCompoundNode(CompoundNode& cNode) { …Run Code Online (Sandbox Code Playgroud) // Create a scanner that reads from the input stream passed to us
CSLexer lexer = new CSLexer(new ANTLRFileStream(f));
tokens.TokenSource = lexer;
// Create a parser that reads from the scanner
CSParser parser = new CSParser(tokens);
// start parsing at the compilationUnit rule
CSParser.compilation_unit_return x = parser.compilation_unit();
object ast = x.Tree;
Run Code Online (Sandbox Code Playgroud)
我怎么能用compilation_unit_return类型的x来提取它的根,它的类,它的方法等?我必须提取其适配器吗?我怎么做?请注意,compilation_unit_return在我的CSParser中定义(由ANTLR自动生成):
public class compilation_unit_return : ParserRuleReturnScope
{
private object tree;
override public object Tree
{
get { return tree; }
set { tree = (object) value; }
}
}; …Run Code Online (Sandbox Code Playgroud) 更新接受了Ira Baxter的回答,因为它指出了我正确的方向:我首先通过开始编译阶段的实现来弄清楚我实际需要什么,很明显很快,节点内的遍历使得这是一个不可能的方法.并非所有节点都应该被访问,其中一些节点的顺序相反(例如,首先是赋值的rhs,因此编译器可以检查类型是否与rhs /运算符匹配).在访问者中进行遍历使得这一切变得非常简单.
在决定对应用程序中使用的迷你语言的处理进行重大修改之前,我正在玩AST和类似的东西.我已经构建了一个Lexer/Parser,可以让AST很好.还有一个访问者,作为具体实现,我创建了一个ASTToOriginal,它只是重新创建原始源文件.最终,还有一些编译器也可以实现Vsisitor并在运行时创建实际的C++代码,所以我想确保一切从一开始就是正确的.虽然现在一切正常,但由于遍历顺序在访问者本身中实现,因此存在一些相似/重复的代码.
在查找更多信息时,似乎某些实现更喜欢在访问对象本身中保留遍历顺序,以便不在每个具体访问者中重复此操作.即便是GoF也只是以同样的方式对此进行了简要的讨论.所以我想尝试这种方法,但很快就陷入了困境.让我解释一下.
示例源代码行和相应的AST节点:
if(t>100?x=1;sety(20,true):x=2)
Conditional
BinaryOp
left=Variable [name=t], operator=[>], right=Integer [value=100]
IfTrue
Assignment
left=Variable [name=x], operator=[=], right=Integer [value=1]
Method
MethodName [name=sety], Arguments( Integer [value=20], Boolean [value=true] )
IfFalse
Assignment
left=Variable [name=x], operator=[=], right=Integer [value=1]
Run Code Online (Sandbox Code Playgroud)
一些代码:
class BinaryOp {
void Accept( Visitor* v ){ v->Visit( this ); }
Expr* left;
Op* op;
Expr* right;
};
class Variable {
void Accept( Visitor* v ){ v->Visit( this ); }
Name* name;
};
class Visitor { //provide basic traversal, terminal …Run Code Online (Sandbox Code Playgroud) 我想知道是否有一个好的设计模式或成语来实现以下内容:
您有一个仅提供访问者界面的现有类,如下所示
Run Code Online (Sandbox Code Playgroud)class Visitor { public: virtual ~Visitor() { } virtual void visit(Node *n) = 0; }; class Tree { public: void accept(Visitor *v); };并且您希望有一个可以按如下方式使用的接口,它应该按照访问者
visit调用其函数的顺序遍历树.Run Code Online (Sandbox Code Playgroud)for(iterator it(...), ite(...); it != ite; ++it) { /* process node */ }
问题似乎是当我们刚刚调用时visit,我们失去控制,并且不能暂时"返回"循环体来执行一个节点的操作.这看起来应该在现实世界的程序中定期出现.知道怎么解决吗?
我正在使用SimpleXML框架反序列化后端答案.我对元素做了一些假设.有些元素不符合这些要求.例如,我希望一个元素有孩子<ID>和<face>.如果不允许我的用户查看特定元素,我可能会得到这样的答案:
<list>
<voucher type="hiddenobject">
<face>foo</face>
</voucher>
<voucher type="object">
<ID>42</ID>
<face>bar</face>
</voucher>
</list>
Run Code Online (Sandbox Code Playgroud)
这给了我以下反序列化类的ValueRequiredException:
@Root
class Voucher {
@Element(name="ID")
private String id;
@Element
private String face;
}
Run Code Online (Sandbox Code Playgroud)
我想用类型忽略这些对象hiddenobject.我了解了VisitorStrategy并实现了Visitor这样一个简单:
private static final class HiddenObjectVisitor implements Visitor {
@Override
public void read(Type type, NodeMap<InputNode> node) throws Exception {
String nodeType = node.getNode().getAttribute("type").getValue();
if (nodeType != null && nodeType.equals("hiddenobject")) {
Log.d(TAG, "skipping node " + node);
node.getNode().skip();
}
}
@Override
public void write(Type type, …Run Code Online (Sandbox Code Playgroud) visitor ×10
c++ ×4
java ×4
antlr ×2
antlr4 ×1
c# ×1
components ×1
game-engine ×1
object-graph ×1
oop ×1
templates ×1