我有一个界面,我们可以称之为“服务器”
class MsgHandler {
public:
virtual void handleMsg1(int x) = 0;
virtual void handleMsg2(int x) = 0;
virtual void handleMsg3(int x) = 0;
};
class Server {
public:
void setMsgHandler(MsgHandler *h) { currentHandler = h; }
MsgHandler* getMsgHandler() { return currentHandler; }
private:
MsgHandler *currentHandler;
};
和一个HandlerA类:
class HandlerA : public MsgHandler {
public:
HandlerA(Server& s) : server(s) {}
void handleMsg1(int x) override { /* do something */ }
void handleMsg2(int x) override {
// do something more
server.setMsgHandler(new HandlerB(s)); // Note that we change Handler here!
}
void handleMsg3(int x) override; // I'll come back to this below
private:
Server &server;
};
和HandlerB:
class HandlerB : public MsgHandler {
public:
HandlerB(Server& s) : server(s) {}
void handleMsg1(int x) override { /* do nothing */ }
void handleMsg2(int x) override { /* do nothing */ }
void handleMsg3(int x) override { /* do something really complex here */ }
private:
Server &server;
};
现在,让我们假设我有一个类似这样的应用程序
Server s;
s.setMsgHandler(new HandlerA(s));
s.getMsgHandler()->handleMsg1(0); // Handled by HandlerA
s.getMsgHandler()->handleMsg2(43); // Handled by HandlerA
s.getMsgHandler()->handleMsg3(99); // Handled by HandlerB
到目前为止一切顺利。但是,我们假设我的应用程序是任意的/非确定性的,因此我们有时可能会得到这个序列:
Server s;
s.setNextMsgHandler(new HandlerA(s));
s.getMsgHandler()->handleMsg1(0);
s.getMsgHandler()->handleMsg3(99); // msg3 comes before msg2!!
s.getMsgHandler()->handleMsg2(43);
我想在HandlerA中做的事情是这样的:
void HandlerA::handleMsg3(int x) {
putMsgInQueue(MsgHandler::handleMsg3, x); // pseudo code!
}
然后我可以通过队列,也许做这样的事情
s.setNextMsgHandler(new HandlerA(s));
s.getMsgHandler()->handleMsg1(0);
s.getMsgHandler()->handleMsg3(99); // msg3 comes before msg2, no problem
s.getMsgHandler()->handleMsg2(43);
processMsgFromQueue(s.getMsgHandler(), ...);
这个排队会简化我的代码,因为handleMsg3()可能非常复杂,并且可能还需要我在handleMsg2()中获得的信息。
我的问题是:如何实现putMsgInQueue(...)/ processMsgFromQueue()或类似的东西?我想我想要一种方法来保存对虚方法的引用在基类中。稍后当我想调用该方法时,调用它实际上会导致对子类的调用。
在给出过于简单/过于复杂的答案之前,请考虑以下事项: - )