Создание события, подобного системе подписки для символов C ++ * - PullRequest
0 голосов
/ 20 января 2011

Для простых данных, таких как целые или константы, что-то вроде этого будет работать

#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() ;
}

Итак, представьте, что мы работаем с некоторым буфером данных, таким как char.

У нас есть потоки, которые ждут указатели данных, и при появлении указатели хотят изменить данные одновременно. Таким образом, нам нужно будет создать копии этих данных и дать каждому подписчику указатель на свою собственную копию.

Так как это сделать? (извините, C ++ nube - код - это единственное, что я могу понять)

1 Ответ

2 голосов
/ 20 января 2011

Рассмотрите сходства между каждым узлом графа, который вы описываете, и создайте для них класс (класс GraphElement ниже).Он должен инкапсулировать свои отношения с дочерними узлами и что-то делать локально с любыми входящими сообщениями (функция localAction).Затем вы должны получить классы, которые представляют конкретные варианты - например, упомянутый вами генератор изображений - и изменить локальное действие.Каждый класс может взять копию исходного сообщения или изменить его по своему усмотрению.

В моем примере кода здесь я создал узел графа по умолчанию - GraphNode - и заставил его просто печатать входящие сообщения перед передачей их дочерним узлам.Я использовал строковый объект для входящего сообщения - намного лучше, чем обычный старый массив C char * [пример: вы можете получить строку из char *, когда message2 создается в приведенном ниже коде].Я сделал эти ссылки на объекты const как дешевые, быстрые и никогда не изменяющие оригинал.

Я получил класс CatNode в качестве примера необходимой вам вариации.Объекты этого типа содержат историю всех сообщений и распечатывают эту историю при поступлении нового сообщения.Не очень полезный, но тем не менее хороший пример.Это демонстрирует, как каждый узел может сделать что-нибудь с копией исходного сообщения - переписать localAction ().Он также передает эту историю любым дочерним узлам - перезаписать входящие сообщения с изменением параметра, переданного в функцию deliveryMessage ().

#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 ]
...