如何处理dervied类的多个重载,而无需对其他文件进行多次更改

时间:2016-04-02 21:34:44

标签: c++ oop inheritance overloading

我不确定如何说出这个问题的标题,但这是我的问题:

我正在使用实体组件系统架构开发C ++游戏。在此体系结构中,每个游戏对象都表示为一个类:

class Object

一个类只不过是组件的容器,它处理游戏对象逻辑的一部分。

class Component

每个组件都有针对特定事件的更新功能和事件处理程序。每个事件都来自一个公共基类,每个子对象都有自己的数据字段来描述事件。在我的实际代码中,基本Event类具有一些所有Events共享的属性。

class Event
{
};

class OnDeathEvent : public Event
{
public:
    int getKillerID() const
    {
        return 92341;
    }
};

class OnLevelEnterEvent : public Event
{
public:
    int getLevelEnteredID() const
    {
        return 100;
    }
};

在整个代码中,我们将事件发送到对象。这是我为测试我的示例代码而编写的主要函数:

int main()
{
    Object obj;
    obj.sendEvent(OnLevelEnterEvent());
    obj.sendEvent(OnDeathEvent());
    std::cin.ignore();
    return 0;
}

当一个Object收到一个事件时,它会将该事件的责任委托给它的组件。

    for (auto& component : components)
    {
        component->handleEvent(e);
    }

我想为每种事件类型使用函数重载。事件处理功能的目的就变得非常明确了。

void handleEvent(const OnLevelEnterEvent& e) 

但这样做需要Object类和Component基类都声明每个Event类型的所有重载。显然,这是我们想要避免的,因为我们必须更改多个类才能为游戏添加新的事件类型。以下是示例代码的其余部分:

class Component
{
public:

    virtual void handleEvent(const Event& e) {}
    virtual void handleEvent(const OnDeathEvent& e) {};
    virtual void handleEvent(const OnLevelEnterEvent& e) {};
};

class TestComponent : public Component
{
public:
    virtual void handleEvent(const OnDeathEvent& e)
    {
        std::cout << "You died. Your killer was: " << e.getKillerID() << std::endl;
    }
};

class AnotherComponent : public Component
{
public:
    virtual void handleEvent(const OnLevelEnterEvent& e) 
    {
        std::cout << "Level Entered with ID: " << e.getLevelEnteredID() << std::endl;
    }
};

对象类:

class Object
{
public:
    Object() 
    {
        components.push_back(new TestComponent());
        components.push_back(new AnotherComponent());
    }


    void sendEvent(const Event& e)
    {
        for (auto& component : components)
        {
            component->handleEvent(e);
        }
    }

    void sendEvent(const OnDeathEvent& e)
    {
        for (auto& component : components)
        {
            component->handleEvent(e);
        }
    }

    void sendEvent(const OnLevelEnterEvent& e)
    {
        for (auto& component : components)
        {
            component->handleEvent(e);
        }
    }

private:
    std::vector<Component*> components;
};

我们希望能够通过继承Event类来添加新的Event类型,而无需更改其他文件或创建新文件(新的Event类除外)。构建代码的优雅方法是什么?

欢迎任何建议。

3 个答案:

答案 0 :(得分:1)

您的组件可以注册该活动。 调用子事件时,它可以通知其注册的事件侦听器。您可以定义一个接口并使用接口继承。

答案 1 :(得分:1)

#include <iostream>
#include <vector>
#include <boost/signals2.hpp>
class Event
{
public:
    typedef boost::signals2::signal<void (Event&) > T_notify_signal;
    virtual ~Event(){}
    void Register(const T_notify_signal::slot_type& c) {m_listeners.connect(c);}
    void NotifyListeners() {m_listeners(*this);}
    virtual std::string info() const = 0;
private:
    T_notify_signal m_listeners;
};
class OnDeathEvent : public Event
{
public:
    virtual ~OnDeathEvent(){}
    virtual std::string info() const { return "you are dead"; }
};
class OnLevelEnterEvent : public Event
{
public:
    virtual ~OnLevelEnterEvent(){}
    virtual std::string info() const { return "you are in a new area"; }
};
//----------------------------------------
class Component
{
public:
    virtual ~Component(){}
};
class TestComponent : public Component
{
public:
    TestComponent(){}
    virtual ~TestComponent(){}
    virtual void notifyLevelEnter(Event& e) {std::cout << "TestComponent::notifyLevelEnter(" << e.info() << ")" << std::endl;}
};
class AnotherComponent : public Component
{
public:
    AnotherComponent(){}
    virtual ~AnotherComponent(){}
    virtual void notifyDeath(Event& e) {std::cout << "AnotherComponent::notifyDeath(" << e.info() << ")" << std::endl;}
    virtual void notifyLevelEnter(Event& e) {std::cout << "AnotherComponent::notifyLevelEnter(" << e.info() << ")" << std::endl;}
};
//----------------------------------------
class Object
{
public:
    Object(){}
    ~Object(){}
    void addComponent( Component& component ) {m_components.push_back( &component );}
    void sendEvent(Event& e) {e.NotifyListeners();}
private:
    std::vector< Component* > m_components;
};
//----------------------------------------
int main()
{
   Object obj;

    // create components
    TestComponent tc;
    AnotherComponent ac;

    // create events
    OnDeathEvent      death_event;
    OnLevelEnterEvent level_enter_event;

    // hook up events to components
    death_event.Register( boost::bind( &AnotherComponent::notifyDeath, &ac, _1 ) );

    level_enter_event.Register( boost::bind( &TestComponent::notifyLevelEnter, &tc, _1 ) );
    level_enter_event.Register( boost::bind( &AnotherComponent::notifyLevelEnter, &ac, _1 ) );

    // add components to object
    obj.addComponent( ac );
    obj.addComponent( tc );

    // process game loop
    while ( true )
    {
        std::cout << "obj.sendEvent(level_enter)" << std::endl;
        obj.sendEvent(level_enter_event);

        std::cout << "obj.sendEvent(death)" << std::endl;
        obj.sendEvent(death_event);

        std::cout << "obj.sendEvent(level_enter)" << std::endl;
        obj.sendEvent(level_enter_event);

        std::cout << "obj.sendEvent(level_enter)" << std::endl;
        obj.sendEvent(level_enter_event);

        std::cout << "obj.sendEvent(death)" << std::endl;
        obj.sendEvent(death_event);
        break;
    }

    return 0;
}

答案 2 :(得分:0)

如果我理解正确,您需要一个sendEvent方法,以及发送任何通用Event类型。在这种情况下,您可以按如下方式创建sendEvent(const Event* _event)方法:

void sendEvent(const Event* _event) {
    for (auto& component : components) {
        component->handleEvent(_event);
    }
}

如果你已经正确地实现了Event的所有派生类,那么多态将处理允许根据handleEvent的特定子类自动调用正确的Event方法的事情。 (以及指向它的指针)传递给sendEvent