使像订阅系统С++ *字符事件

问题描述:

因此,对于像整数或常量像这样简单的数据将工作使像订阅系统С++ *字符事件

#include <iostream> 
#include <vector> 

using namespace std ; 

typedef void FuncInt (int) ; 

class GraphElementProto { 
public: 
    void add (FuncInt* f) 
{ 
    FuncVec.push_back (f) ; 
} ; 
    void call() 
{ 
    for (size_t i = 0 ; i < FuncVec.size() ; i++) 
    FuncVec[i] (i) ; 
} ; 
private: 
    vector<FuncInt*> FuncVec ; 
} ; 


static void f0 (int i) { cout << "f0(" << i << ")" << endl ; } 
static void f1 (int i) { cout << "f1(" << i << ")" << endl ; } 

int main() { 
    GraphElementProto a ; 
    a.add (f0) ; 
    a.add (f1) ; 
    a.call() ; 
} 

所以现在想象我们与像烧焦了一些数据缓冲区工作。

我们有等待数据指针的线程,并且该指针的外观需要同时更改数据。所以我们需要创建该数据的副本,并将每个订阅者指针指向他自己的副本。

那么如何做这样的事情呢? (对不起,C++ nube - 代码只是我能理解的东西)

+2

我不是C++ nube,但我理解你的代码比你的问题好得多。请详细说明 – 2011-01-20 12:28:43

+0

我编辑了这个问题 - 现在看起来好多了。) – Rella 2011-01-20 22:10:04

考虑你描述的图形的每个节点之间的相似之处并为它们创建一个类(下面的GraphElement类)。它应该将其与其子节点的关系封装起来,并且应该在本地对任何传入消息执行一些操作(函数localAction)。然后,您应该派生代表特定变体的类 - 例如您提到的图像生成器 - 并更改本地操作。每个班级可能会收到原始邮件的副本,或者根据需要更改它。

在我的示例代码中,我创建了默认图形节点 - GraphNode - 并将其传递到其子节点之前,简单地打印传入的消息。我为传入消息使用了一个字符串对象 - 比普通的旧C char *数组好得多[例如:当在下面的代码中创建message2时,您可以从char *派生一个字符串]。我将这些对象的const引用作为廉价,快速,永不改变原来的。

我已经派生出一个名为CatNode的类作为您需要的变体的示例。这种类型的对象包含所有消息的历史记录,并在新消息到达时打印出历史记录。不是很有用 - 但是一个很好的例子。这将演示每个节点如何对原始消息的副本执行任何操作 - 重写localAction()。它还将该历史记录传递给任何子节点 - 通过更改传递给deliverMessage()的参数来重写incomingMessage。

#include <vector> 
#include <iostream> 
#include <string> 
using std::cout; 
using std::endl; 
using std::vector; 
using std::string; 

class GraphNode 
{ 
public: 

    GraphNode(string & name) : mChildren(), mName(name) {} 
    GraphNode(const char * const name) : mChildren(), mName(name==NULL?"":name) {} 

    virtual void incomingMessage(const string & str) { 
    localAction(str);  // This node is to do something. 
    deliverMessage(str); // Child nodes are to do things too. 
    } 

    void addChild(GraphNode * child) { 
    mChildren.push_back(child); 
    } 

protected: 

    // Rewrite this function for child classes who are to do different things with messages. 
    virtual void localAction(const string & str) { 
    cout << mName << " : " << str << endl; 
    } 

    void deliverMessage(const string & str) { 
    vector<GraphNode*>::iterator itr = mChildren.begin(); 
    for(; itr != mChildren.end(); ++itr) 
     (*itr)->incomingMessage(str); 
    } 

    // Data members 
    vector<GraphNode*> mChildren; 
    string mName; 

}; // [ GraphNode ] 



class CatNode : public GraphNode 
{ 
public: 

    CatNode(string & name) : GraphNode(name), mHistory() {} 
    CatNode(const char * const name) : GraphNode(name), mHistory() {} 

    virtual void incomingMessage(const string & str) { 
    localAction(str); 
    deliverMessage(mHistory); 
    } 

protected: 

    virtual void localAction(const string & str) { 
    mHistory += str; 
    cout << mName << " : " << mHistory << endl; 
    } 

    // Data members 
    string mHistory; 

}; // [ CatNode ] 



main() 
{ 
    // root -> childA 
    GraphNode root("Root Node"); 
    CatNode childA("Child A"); 
    root.addChild(&childA); 
    root.incomingMessage("Message1"); 
    cout << endl; 

    // root -> childA -> childC 
    //  \-> childB 
    GraphNode childB("Child B"); 
    root.addChild(&childB); 
    GraphNode childC("Child C"); 
    childA.addChild(&childC); 
    string message2("Message2"); 
    root.incomingMessage(message2); 

} // [ main ]