OSG学习笔记2—节点属性访问器

osgStudy4_20.cpp : 定义控制台应用程序的入口点。
节点属性访问器
自定义NodeVisitor并用于节点访问的方法,重构重要的apply()虚函数,在其中打印节点的属性信息(名字和所在库)并通过适当的缩进来表达整个节点树的层次结构。

访问器Visitor,使用典型的对象行为模式,它可以向不同的节点,施加用户自定义的操作,将这些操作整合到一个对象中,同时避免这些操作可能造成的数据结构本身的变化,从而实现了一种更加自由的编码方式。

每个数据元素节点都可以通过accept()方法调用访问器,访问器通过apply()方法获取传入的节点对象,并执行所需的节点操作。

osg::NodeVisitor只是访问器角色的抽象接口。我认为这里的接口不是C++标准定义的接口,查看了源码,在NodeVisitor中定义的是不同节点的apply虚函数,用于用户自定义的Visitor子类的重写,不是纯虚函数,这里书中叫做接口,应该是为了理解吧。

//——C++构造函数初始值列表————
//InfoVisitor():osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), _indent(0){}
//构造函数初始化列表。C++Primer5 P258
//如果没有在构造函数的初始值列表中显式的初始化成员,则该成员在构造函数体之前执行默认初始化,就是通常的类的构造函数写法。
//但有一些数据成员必须被初始化,例如const,或者引用,当成员属于某种类类型且该类没有定义默认构造函数时,必须将这个成员初始化。
//建议:养成使用构造函数初始值的习惯,能避免一些编译错误。
//构造函数名InfoVisitor()后面的“:”后面有两个初始化值,用逗号隔开。前一个应该是因为InfoVisitor这个类继承了NodeVisitor
//在这里就同时为父类初始化了。第二个为_indent初始化为0.

//——C++接口————

提供一个与其他系统交互的方法,为所有子类共同约定一个访问接口,提供给类外面使用的接口一般采用纯虚函数,如:virtual void work()=0;

接口实现:通过继承接口的子类实现,不同的子类可以实现不同的效果,这就是所谓的多态。

//——C++ 虚函数————

//基类将类型相关的函数与派生类不做改变直接继承的函数区别对待。对于某些函数,基类希望它的派生类各自定义适合自己的版本,此时

//基类就将这些函数声明为虚函数virtual,即声明可以被覆盖。子类里的两个apply是重构父类方法的。

//C++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数,因此,子类重新声明该虚函数时,可以加virtual关键字,也可以不加,但加上会更好,让程序层次更清晰。

#include "stdafx.h"
#include<osg/Node>
#include<osgDB/ReadFile>
#include<iostream>


class InfoVisitor :public osg::NodeVisitor{//Step1:继承并编写自己的访问器类
public:
	InfoVisitor()
	:osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), _indent(0){}


	virtual void apply(osg::Node& node)//Step2:重写各个节点类型对应的apply()函数,在其中实现自己所需功能。
	{
		for (int i = 0; i < _indent; ++i) std::cout << " ";
		std::cout << "[" << _indent + 1 << "]" << node.libraryName() << "::" << node.className() << std::endl;


		_indent++;
		traverse(node);
		_indent--;
	}
	virtual void apply(osg::Geode& node)
	{
		for (int i = 0; i < _indent; ++i) std::cout << " ";
		std::cout << "[" << _indent + 1 << "]" << node.libraryName() << "::" << node.className() << std::endl;


		for (unsigned int n = 0; n < node.getNumDrawables(); ++n)
		{
			osg::Drawable*drawable = node.getDrawable(n);
			if (!drawable)continue;


			for (int i = 0; i <= _indent; ++i)std::cout << " ";
			std::cout << drawable->libraryName() << "::" << drawable->className() << std::endl;
		}
		_indent++;
		traverse(node);
		_indent--;
	}
protected:
	int _indent;
};
int _tmain(int argc, char** argv)
{
	osg::ArgumentParser arugments(&argc, argv);
	osg::Node* root = osgDB::readNodeFiles(arugments);
	if (!root) root = osgDB::readNodeFile("axes.osgt");


	InfoVisitor infoVisitor;
	if (root)root->accept(infoVisitor);//Step3:节点接受一个访问器,在accept()中节点执行访问器的apply()




	return 0;
}


你可能感兴趣的:(OSG学习笔记2—节点属性访问器)