C++访问者模式多组件

问题描述

我得到了一个对象树。在对象树中,我存储场景节点。 SceneNode 通常是其他类的基类。 我想为代表场景节点的对象实现不同的行为。

这个问题的正确模式应该是访问者模式。我想遍历 SceneNodes 并想根据存储在 SceneNodes 后面的对象调用不同的函数。 但我不仅希望允许对象树中的一个对象成为访问者模式的一个组件,而且还希望共享功能。

例如:我有一个 BaseObject。我可以更新这个 BaseObject(例如到一个新位置),我可以绘制一个 BaseObject(OpenGL 的东西)。 但我也有一个 Camera 对象。相机对象可以更新但不能绘制。

这是访问者资料的实现:

class Visitor 
{
public:
    virtual void VisitUpdate(ComponentUpdate* element) = 0;
    virtual void VisitDraw(ComponentDraw* element) = 0;
    virtual void VisitOverlay(ComponentOverlay* element) = 0;
};

访问者组件:

class Component
{
public:
    virtual ~Component() { }
    virtual void accept(Visitor* visitor) = 0;
};

具体组件:

class ComponentUpdate : public Component
{
public:
    void accept(Visitor* visitor) override {
        visitor->VisitUpdate(this);
    }

    virtual void update() = 0;
};

class ComponentDraw : public Component
{
public:
    void accept(Visitor* visitor) override {
        visitor->VisitDraw(this);
    }

    virtual void draw() = 0;
};

最后是一个具体的访客:

class SceneNodeVisitor : public Visitor
{
    void VisitUpdate(ComponentUpdate* element) override {
        element->update();
    }

    void VisitDraw(ComponentDraw* element) override {
        element->draw();
    }
};

现在我想做这样的事情:

class Camera : public ComponentUpdate
{
    void update() override { std::cout << "Camnera update" << std::endl; }
};

class ObjectBase : public ComponentDraw,public ComponentUpdate
{
    void update() override { std::cout << "ObjectBase update" << std::endl; }
    void draw() override { std::cout << "ObjectBase draw" << std::endl; }
};

好的,到目前为止一切顺利。我现在的问题是编译器说“基类不明确”。我认为这是不正确的,因为 ObjectBase 是不明确的,因为它有两个不同的 accept() 函数,对吗?

有没有办法使用访问者模式,以便我可以自由地为类添加我需要的功能?

这里的主要功能:

int main() {
    ObjectBase ob;
    Camera cam;
    SceneNodeVisitor visitor;

    std::vector<Component*> components;
    components.push_back(new Camera);
    components.push_back(new ObjectBase);
    components[0]->accept(&visitor);
    components[1]->accept(&visitor);
}

奇怪的是我可以在堆栈上创建ObjectBase。如果我尝试在堆上创建对象(通过 new),我只会收到错误消息。

Pastebin 目前已关闭,我可以在它再次启动后立即提供此示例代码。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)