所以我使用Open Scene图创建一个应用程序,我有一个从OSG的回调类扩展的回调类 . 它只是一个回调,在场景图节点的更新事件遍历中称为每个帧 .
我需要不同的回调类,它们在附加到的节点上执行不同的操作 . 所以我有一个基本的回调类,我称之为控制器基:
class ControllerBase : public osg::NodeCallback
{
public:
ControllerBase();
private:
// operator is overridden here from NodeCallback and is called each frame.
virtual void operator()(osg::Node * n, osg::NodeVisitor * nv);
}
operator()为我提供了附加回调的节点和节点访问者 . 现在,根据节点,它可能是一个不同的类,如变换或开关 .
所以我需要进行动态转换,但对于每个可能的类型,节点可能是 . 所以:
class ControllerBase : public osg::NodeCallback
{
public:
ControllerBase();
private:
virtual void operator()(osg::Node * n, osg::NodeVisitor * nv)
{
Type1 * t1 = dynamic_cast<Type1*>(node);
Type2 * t2 = dynamic_cast<Type1*>(node);
Type3 * t3 = dynamic_cast<Type1*>(node);
}
}
然后通过虚拟方法将它们发送出去,由我将附加到节点的特定控制器类继承 .
class ControllerBase : public osg::NodeCallback
{
public:
ControllerBase();
protected:
private:
virtual void On_Frame(Type1*, osg::NodeVisitor) = 0;
virtual void On_Frame(Type2*, osg::NodeVisitor) = 0;
virtual void On_Frame(Type3*, osg::NodeVisitor) = 0;
virtual void operator()(osg::Node * n, osg::NodeVisitor * nv)
{
Type1 * t1 = dynamic_cast<Type1*>(node);
Type2 * t2 = dynamic_cast<Type1*>(node);
Type3 * t3 = dynamic_cast<Type1*>(node);
if(t1)
On_Frame(t1, nv);
if(t2)
On_Frame(t2, nv);
if(t3)
On_Frame(t3, nv);
}
}
class Type1_Controller
{
public:
Type1_Controler();
private:
virtual void On_Frame(Type1 * type, osg::NodeVisitor *nv) override
{
// Do type 1 related stuff here.
}
virtual void On_Frame(Type2 * type, osg::NodeVisitor *nv) override
{
// Leave empty, not needed.
}
virtual void On_Frame(Type3 * type, osg::NodeVisitor *nv) override
{
// Leave empty, not needed.
}
}
所以现在对于我所拥有的每种类型的控制器,我必须实现剩余的空方法 . 这感觉就像糟糕的设计,但我无法弄清楚如何编写更好的实现 . 也许它不是那么糟糕的3种类型,但随着我的进展,我可能还需要添加更多内容 . 我想过使用模板类,但如果我没弄错,我就不能在模板类中使用虚方法 . 我可以使用非纯虚方法和空实现,我想可以在选择时重写 . 什么是好的方法或建议?
2 回答
osg :: NodeVisitor或多或少是访问者设计模式的教科书实现 . (有关原始"Gang of Four"或GoF书籍的更多信息,请参阅http://en.wikipedia.org/wiki/Design_Patterns) .
您可以覆盖t1节点类中的accept(NodeVisitor)以尝试转换为您的t1访问者类型,例如:
当然,还有一点,但这是GoF书中提出的双重调度的一般概念 .
根据您的设计,它看起来像类 -
Type1, Type2, Type3
都来自osg::Node
. 在这种情况下,为什么要使用dynamic_cast并尝试确定operator()重载中的类型?你可以在ControllerBase
中执行此操作 -然后在
Type1_Controller
,Type2_Controller
等每一个中都有一个On_Frame方法 -