Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 场景图更新回调设计_C++_Oop_Design Patterns_Callback_Openscenegraph - Fatal编程技术网

C++ 场景图更新回调设计

C++ 场景图更新回调设计,c++,oop,design-patterns,callback,openscenegraph,C++,Oop,Design Patterns,Callback,Openscenegraph,所以我使用OpenSceneGraph来创建一个应用程序,我有一个从OSG的回调类扩展而来的回调类。它只是一个回调,在场景图节点的更新事件遍历中调用每个帧 我需要不同的回调类,它们在所连接的节点上执行不同的操作。因此,我有一个基本回调类,我称之为控制器基: class ControllerBase : public osg::NodeCallback { public: ControllerBase(); private: // operator is overridden he

所以我使用OpenSceneGraph来创建一个应用程序,我有一个从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);
}
运算符()为我提供了回调所附加的节点和节点访问者。现在,根据节点的不同,它可能是一个不同的类,例如转换或开关

因此,我需要进行动态转换,但对于每个可能的类型,节点都可能是。因此:

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
{
公众:
ControllerBase();
私人:
虚拟void操作符()(osg::Node*n,osg::NodeVisitor*nv)
{
类型1*t1=动态_转换(节点);
类型2*t2=动态_投射(节点);
类型3*t3=动态广播(节点);
}
}
然后通过虚拟方法将它们发送出去,由我将附加到节点的特定控制器类继承

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. 
        }
}
class ControllerBase:public osg::NodeCallback
{
公众:
ControllerBase();
受保护的:
私人:
_帧上的虚拟空白(类型1*,osg::NodeVisitor)=0;
_帧上的虚拟空(类型2*,osg::NodeVisitor)=0;
_帧上的虚拟空间(类型3*,osg::NodeVisitor)=0;
虚拟void操作符()(osg::Node*n,osg::NodeVisitor*nv)
{
类型1*t1=动态_转换(节点);
类型2*t2=动态_投射(节点);
类型3*t3=动态广播(节点);
if(t1)
在_帧上(t1,nv);
if(t2)
在帧上(t2,nv);
国际单项体育联合会(t3)
在机架上(t3,nv);
}
}
类类型1_控制器
{
公众:
类型1_控制器();
私人:
U帧上的虚拟无效(类型1*类型,osg::NodeVisitor*nv)覆盖
{
//在这里做1类相关的事情。
}
帧上的虚拟无效(类型2*类型,osg::NodeVisitor*nv)覆盖
{
//留空,不需要。
}
_帧上的虚拟无效(类型3*type,osg::NodeVisitor*nv)覆盖
{
//留空,不需要。
}
}

所以现在对于我拥有的每种类型的控制器,我必须实现剩余的空方法。这感觉像是糟糕的设计,但我不知道如何编写更好的实现。也许这3种类型没那么糟糕,但随着时间的推移,我可能还有更多的东西要补充。我考虑过使用一个模板类,但如果我没有弄错的话,我不能在模板类中使用虚拟方法。我可以只使用带有空实现的非纯虚拟方法,我想可以选择重写它。一个好的方法是什么或建议什么

根据您的设计,类-
Type1、Type2、Type3
都源自
osg::Node
。在这种情况下,为什么要使用动态_强制转换并尝试确定运算符()重载中的类型?您可以在
ControllerBase
-

virtual void operator()(osg::Node * n, osg::NodeVisitor * nv)
{
  On_Frame(n, nv);
}
然后在
Type1\u控制器
Type2\u控制器
等中的每一个都有一个单帧方法,如-

virtual void On_Frame(osg::Node * n, osg::NodeVisitor *nv) override
{
   Type1 * t1 = dynamic_cast<Type1*>(n);
    if(t1)
    {
       // only if t1 do something
    }
 }
帧上的虚拟无效(osg::Node*n,osg::NodeVisitor*nv)覆盖
{
类型1*t1=动态铸型(n);
if(t1)
{
//只有t1做点什么
}
}

osg::NodeVisitor或多或少是访问者设计模式的教科书式实现。(有关原始“四人帮”或GoF书籍的更多信息,请参阅)

您可以覆盖t1节点类中的accept(NodeVisitor)以尝试强制转换为t1访问者类型,例如:

 Type1_Visitor* vis = dynamic_cast<NodeVisitor> nv;
 if(vis)
    vis->Type1Apply(*this);
 else
    nv->apply(*this);
Type1_Visitor*vis=dynamic_cast nv;
if(vis)
vis->类型1应用(*本);
其他的
nv->apply(*此项);

当然,还有一点,但这是GoF书中所阐述的双重派遣的一般概念。

你可能是对的。在某些情况下,我会为所有使用Type1的对象设置不同的控制器类。我只是觉得在一个地方处理动态转换会更好,而不是在每个单独的控制器类中。但我想这就是我必须要做的。即使多个控制器类附加到同一类型的对象,我认为通过在On_Frame函数中进行适当的处理,它仍然可以正常工作:)