对于像int或常量这样的简单数据,这样的东西可以起作用
#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 - 代码只是我能理解的东西)
答案 0 :(得分:2)
考虑您描述的图形的每个节点之间的相似性,并为它们创建一个类(下面的类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 ]