这是多态性的恰当用途吗?

时间:2011-03-04 19:05:14

标签: c++ polymorphism

考虑这个语法正确的(?)伪代码:

class Event {
public:
    virtual int getID() const = 0;
    virtual int getSize() = 0;
    virtual void* getData() = 0;
    virtual void setData() = 0;
    //(I cannot define data at this level 'cos I don't know what it is yet)
}

class SpecialEvent : class Event {
public:
    virtual int getPGNID() const = 0;
    int getSourceAddress() {return source_address;}
    int setSourceAddress(int source_address) {this->source_address = source_address;}
protected:
    int source_address;
}

template <typename T, typename E>
class EventWrapper : public E {
    T data;
public:
    static int EVENT_ID;
    //implements everything in Event...EVENT_ID is assigned at runtime by some registry
}

class AnEvent : public EventWrapper<int, Event> {
     //public methods specific to AnEvent...
}

class AnotherEvent : public EventWrapper<long, SpecialEvent> {
    int getPGNID() const {static int ID = 10; return ID;}
}

class TheProcessingClass {
    AnEvent event1;
    AnotherEvent event2;

    void process(Event& e);
    void process(SpecialEvent& e);

    void doSomething() {
        process(event1);  //should invoke process(Event&)
        process(event2);  //should invoke process(SpecialEvent&)
    }
}

基本上,我有一个包装类,它包装类型为T的数据,并从某种类型的E继承(在本例中为EventSpecialEvent)...

我最初打算创建两个包装类EventWrapperSpecialEventWrapper,直到我发现两个类中都有完全相同的代码(只要它从某种类型的{ {1}})

首先,这听起来像是基于策略的设计。但是,Event没有任何特殊行为......他们只是持有一些数据......我是否滥用这种模式?

第二关,有更好的方法吗?我在这里大大简化了一些事情,但任何见解都会受到赞赏......

修改 我更新了我的示例......简而言之,处理类正在侦听事件,应该根据事件采取行动。我希望这有帮助...

3 个答案:

答案 0 :(得分:1)

我建议添加process()作为类事件的成员函数。

class Event {
    int getID() const;
    void process();
    //class stuff
}

class SpecialEvent : class Event {
    int getSpecialID() const;
    void process(); //special version of process()
    //class stuff
}


class TheProcessingClass {
    Event event1;
    SpecialEvent event2;

    void doSomething() {
        event1.process();
        event2.process();
    }
}

答案 1 :(得分:0)

我已经使用了你的代码一段时间了。 在我看来,你正在尝试做一些非常像boost::any

的事情

如果不是,我的主要建议是为Event和SpecialEvent使用真正的抽象接口。你所拥有的设计只是部分多态,因为SpecialEvent有一个方法,更重要的是一个IDENTITY方法,它不会覆盖Event :: getId。这种“感觉”非常糟糕,我相信当你以任何通用的方式依赖Id概念时,我都相信会让你陷入困境。

在您的设计中,您需要在类(类型)标识和对象(实例)标识之间建立明确的区别。到目前为止,您似乎只使用对象(实例)标识,否则您的id()方法将是静态的。 RTTI可用于建立类标识,但取决于实际的派生类型是典型的反模式,通常表示破坏的多态性。我从来不需要RTTI,甚至不需要记录。

答案 2 :(得分:0)

回答问题的关键代码是两个流程函数及其功能。将SpecialEvent派生的SpecialEvent或EventWrapper传递给process(Event&)函数是不正确的?如果是这样,那么这不适合使用多态。