osg::ref_ptr< osg::Node> model;
NodeVisitor vv( TRAVERSE_ALL_CHILDREN);
model->accept( vv);
假设model的模型结构如图:
则model->accept( vv);多态,相当于调用Group::accept(NodeVisitor)。
注意,我开始误认为Group没有对accept()进行重写,
但后来在遍历Geode结点时,发现Geode类的定义中有一个META_Node(osg, Geode),才发现这些节点都调用了META_Node宏,而
META_Node宏里有个virtual void accept(osg::NodeVisitor& nv)
{ if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); }
原来这些节点都重写accept虚函数。这样才是正确的。这个宏定义代码和voidNode::accept(NodeVisitor& nv)的实现完全相同。
将Group的META_Node宏中的accept展开,为:
void Group::accept(NodeVisitor& nv)
{
if (nv.validNodeMask(*this))
{
nv.pushOntoNodePath(this);
nv.apply(*this);
nv.popFromNodePath();
}
}
其中nv.apply(*this);因为this指针是Group*型,所以实际调用的是NodeVisitor::apply( Group& node),其中node指向Group对象
(注:如果是void Node::accept(NodeVisitor& nv){nv.apply(*this);} 则调用的不是NodeVisitor::apply( Group& node),因为nv.apply(*this)中的this参数是Node*型,
应与apply( Node*)匹配,而apply( Group*)则无法匹配,因为Node*不能隐式转换为Group*。示例程序如文章最后):
void NodeVisitor::apply(Group & node)
{
traverse(node);
}
NodeVisitor类中
inline void traverse(Node& node)
{
if (_traversalMode==TRAVERSE_PARENTS) node.ascend(*this);
else if (_traversalMode!=TRAVERSE_NONE) node.traverse(*this);
}
由于此程序代码中NodeVisitor设置的遍历模式为TRAVERSE_ALL_CHILDREN(而不是默认的TRAVERSE_NONE),故调用Group::traverse(NodeVisitor):
void Group::traverse(NodeVisitor& nv)
{
for(NodeList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
(*itr)->accept(nv);
}
}
表示对其每一个孩子进行遍历,递归调用。相当于深搜。
附:
Node类的traverse()函数为空:
virtual void traverse(NodeVisitor& /*nv*/) {}
递归调用过程如下图:
对以下代码:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class A;
class B;
class NodeVisitor
{
public:
void apply( A& a)
{
cout<< "apply( A& a)"<< endl;
}
void apply( B& b)
{
cout<< "apply( B& b)"<< endl;
}
};
class A
{
public:
void accept( NodeVisitor& nv)
{
nv.apply( *this);//this是A*型,故调用apply( A*),即apply( A& a)
}
};
class B: public A
{};
int _tmain(int argc, _TCHAR* argv[])
{
B b;
NodeVisitor nv;
b.accept( nv);//最终调用apply( A& a)。
system("pause");
return 0;
}
如果上述代码中实现了B的accept(),则:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class A;
class B;
class NodeVisitor
{
public:
void apply( A& a)
{
cout<< "apply( A& a)"<< endl;
}
void apply( B& b)
{
cout<< "apply( B& b)"<< endl;
}
};
class A
{
public:
void accept( NodeVisitor& nv)
{
nv.apply( *this);//this是A*型,故调用apply( A*),即apply( A& a)
}
};
class B: public A
{
public:
void accept( NodeVisitor& nv)
{
nv.apply( *this);//this是B*型,故调用apply( B*),即apply( B& b)
}
};
int _tmain(int argc, _TCHAR* argv[])
{
B b;
NodeVisitor nv;
b.accept( nv);//调用B::accept(),最终调用apply( B& b)。
system("pause");
return 0;
}
―――――――
Visitor模型示例如下:
class Node;
class Node_derived1;
class NodeVisitor
{
public:
virtual void apply( Node& n)
{
cout<< "NodeVisitor::apply( Node& n)"<< endl;
}
virtual void apply( Node_derived1& n)
{
cout<< "NodeVisitor::apply( Node_derived1& n)"<< endl;
}
};
class NodeVisitor_Derived1: public NodeVisitor
{
public:
virtual void apply( Node& n)//重写有关Node基类的函数
{
cout<< "NodeVisitor_Derived1::apply( Node& n)"<< endl;
}
virtual void apply( Node_derived1& n)//写自定义的函数
{
cout<< "NodeVisitor_Derived1::apply( Node_derived1& n)"<< endl;
}
};
class Node
{
public:
virtual void accept( NodeVisitor& nv)
{
nv.apply( *this);//this为Node*,与apply( Node*)匹配,调用apply( Node & n)
}
};
class Node_derived1: public Node
{
public:
virtual void accept( NodeVisitor& nv)
{
nv.apply( *this);//this为Node_derived1*,与apply(Node_derived1*)匹配,调用apply( Node_derived1& n)
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Node n;
NodeVisitor nv;
n.accept( nv);//调用NodeVisitor::apply( Node& n)
Node_derived1 n1;
NodeVisitor_Derived1 nv1;
n1.accept( nv1);//调用NodeVisitor_Derived1::apply( Node_derived1& n)
system("pause");
return 0;
}
Node和NodeVisitor分别是节点基类,节点访问器基类。可以从它们继承,如Node_derived1对应NodeVisitor_Derived1。
如果想再添加Node_derived2~NodeVisitor_Derived2、Node_derived3~NodeVisitor_Derived3。但有个缺点,
就是每次除了加2个类,还需修改NodeVisitor基类,即在NodeVisitor类中加入virtualvoid apply( Node_derived_N& n)。
―――――――――――
OSG中的Node、Group、Geode的访问如下:
void NodeVisitor::apply(Node& node)
{
traverse(node);
}
void NodeVisitor::apply(Group& node)
{
traverse(node);
}
void NodeVisitor::apply(Geode& node)
{
apply(static_cast<Node&>(node));
}
inline void NodeVisitor::traverse(Node& node)
{
if (_traversalMode==TRAVERSE_PARENTS) node.ascend(*this);
else if (_traversalMode!=TRAVERSE_NONE) node.traverse(*this);
}
void Node::accept(NodeVisitor& nv)
{ if (nv.validNodeMask(*this))
{
nv.pushOntoNodePath(this);
nv.apply(*this);
nv.popFromNodePath();
}}
virtual void Node::traverse(NodeVisitor& /*nv*/) {}
virtual void Group::accept(osg::NodeVisitor& nv)
{ if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); }}
void Group::traverse(NodeVisitor& nv)
{
for(NodeList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
(*itr)->accept(nv);
}}
virtual void Geode::accept(osg::NodeVisitor& nv)
{ if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); }}