osg::Object类作为osg中绝大多数类的基类,通过方法(提供的接口)和属性,代表的都是最基本的。
先抛出一个悬而未解的疑问就是类中重要受保护类型的变量osg::UserDataContainer * 为什么没用智能指针?
osg::Object可以说是个数据基类,它一定维护最基本最重要的数据,和对数据进行的最基本最重要的操作接口。
先说其中有几个方法通过osg::UserDataContainer来实现的。osg::UserDataContainer类主要维护一个Userdata和若干UserObject。osg::Object的set/getUserValue,是一对操作,set和get的都是写死的osg::Object继承类TemplateValueObject<T>(一个类似键值对的类)来实现name和value对应存取的功能。
然后就是DataVariance枚举类型,来定义数据变化类型。有个compute方法是个接口,其子类可以实现然后自动检测子类是否维护了几个重要回调,来自动确认数据变化类型。
还有比较重要的工作就是对这个数据类及其继承类的数据拷贝问题。深拷贝浅拷贝就不说了,单看拷贝的写法就有几种,值得注意的是operator=运算符已经定义为私有的了,除非子类定义为共有否则没法使用,所以一般也就不用来做数据拷贝了,而且如果是在初始化中即使用=号运算符,也会执行拷贝构造函数。
可以自己试一下以下代码:
#include <iostream>
class A
{
public:
A(){std::cout<<"new A"<<std::endl;}
A(const A& a){std::cout<<"A copy"<<std::endl;}
private:
A& operator=(const A&){std::cout<<"A operator="<<std::endl;}
};
class B : public A
{
public:
B(){std::cout<<"new B"<<std::endl;}
B(const B& b):A(b)
{
std::cout<<"B copy"<<std::endl;
}
// B& operator=(const B&){std::cout<<"B operator="<<std::endl;return *this;}
};
void main()
{
B* b = new B;
B* c = new B(*b);
B d = *c; //B d;d = *c;
}
现在说osg中拷贝一个对象的问题。直接调用拷贝构造函数bingo~,调用clone方法bingo~,调用osg::clone函数就未必能返回想要的了。
直接调用构造函数很直接想到的办法。
clone(包括cloneType)方法,是为了配合全局osg::clone函数工作的,如果要克隆的对象没有重写clone方法,则不会成功返回克隆对象。这样就确保了返回的对象一定是想要返回的被正确克隆的继承类。