Возможно, рассмотрите возможность использования шаблона наблюдателя (http://en.wikipedia.org/wiki/Observer_pattern).
Таким образом, ваш отправитель не знает вашего получателя, а ваш наблюдатель может контролировать распространение сообщений.
Отправитель -> информирует наблюдателя о наличии сообщения.
наблюдатель -> информирует каждую заинтересованную сторону о новом сообщении.
заинтересованная часть -> делает забавные вещи.
Для этого потребуется какая-то система идентификации msg. Возможно, все сообщения могут наследоваться от типа сообщения, имеющего член типа и член идентификатора. Таким образом, вы можете зарегистрироваться для сообщений, используя их.
Обновлять:
Краткая структура сообщения:
class Message
{
public:
size_t m_Type;
size_t m_Id;
protected:
Message(size_t type, size_t id) : m_Type(type), m_Id(id) {}
};
class Type1 : public Message
{
public:
static const size_t type = 1;
Type1(size_t id) : Message(type, id) {}
};
Подписчик означает человека, который хочет прослушать сообщение). Подписчик должен иметь интерфейс для приема сообщений, основанный на обеих этих функциях.
Class subscriber
{
virtual void receiveType(size_t type, char * data) = 0;
virtual void receiveMsg(size_t type, size_t id, char * data) = 0;
};
У наблюдателя должен быть метод регистрации для сообщений:
Class Observer
{
void registerForType(type, subscriber);
void registerForMsg(type, id, subscriber);
};
Другое обновление:
На самом деле это просто грубое доказательство концепции. Можно делать то, что вы хотите, не зная точной цепочки предков. Простите переключение функций триггера и регистрации входа (сначала сделал неправильно, и это было самое простое исправление, опять же proof-of-concept). Другим недостатком этого скетча является то, что для регистрации необходимо создать как минимум сообщение. Если вы ищете действительно долгосрочное решение, я предлагаю вам найти библиотеку или фреймворк, в котором уже есть отражение (например, QT имеет метаобъекты), их можно использовать для просмотра суперклассов. Или вы можете использовать уже имеющиеся сигналы/слоты.
Вывод из приведенного ниже кода:
Начиная с C:\Users\David\Downloads\asdf-build-desktop-Qt
#include <string>
#include <vector>
#include <map>
#include <stdio.h>
using namespace std;
class BaseMsg
{
public:
BaseMsg()
{
theRealInit();
}
//incase you don't want to go all the way down the rabbit hole.
//At the bottom they are the same
virtual vector<string> const & registrationEntries() const {return m_SubClassChain;}
virtual vector<string> const & triggerEntries() const {return m_SubClassChain;}
protected:
virtual void init() { printf("Should NOT CALL THIS HERE!");}
vector<string> m_SubClassChain;
private:
void theRealInit()
{
m_SubClassChain.push_back("BaseMsg");
}
};
class Message : public BaseMsg
{
public:
Message() : BaseMsg()
{
init(); //MUST BE CALLED from child
}
virtual vector<string> const & triggerEntries() const {return m_TriggerEntries;}
protected:
virtual void init()
{
//BaseMsg::init();
m_SubClassChain.push_back("Message");
m_TriggerEntries.push_back("Message");
}
private:
vector<string> m_TriggerEntries;
};
class Subscriber
{
public:
virtual void newMessage(BaseMsg const & i_msg)
{
printf("%s\n", __PRETTY_FUNCTION__);
}
};
class Subscriber2 : public Subscriber
{
public:
virtual void newMessage(BaseMsg const & i_msg)
{
printf("%s\n", __PRETTY_FUNCTION__);
}
};
class Subscriber1 : public Subscriber
{
public:
virtual void newMessage(BaseMsg const & i_msg)
{
printf("%s\n", __PRETTY_FUNCTION__);
}
};
class Sender
{
//typdef vector<Receiver const & > Receivers;
public:
void registerForMsg(Subscriber * someoneThatCares, BaseMsg const & msg)
{
vector<string> const & triggers = msg.triggerEntries();
vector<string>::const_iterator it = triggers.begin();
for(; it != triggers.end(); it++)
{
printf("Registration: %s\n", it->c_str());
m_routingMap.insert(pair<string, Subscriber *>(*it, someoneThatCares));
}
}
void send(BaseMsg const & msg)
{
vector<string> const & triggers = msg.registrationEntries();
vector<string>::const_iterator it = triggers.begin();
for(; it != triggers.end(); it++)
{
printf("Trigger: %s\n", it->c_str());
pair<multimap<string, Subscriber *>::iterator, multimap<string, Subscriber *>::iterator> ret;
//borrowed from: http://www.cplusplus.com/reference/stl/multimap/equal_range/
ret = m_routingMap.equal_range(*it);
multimap<string, Subscriber *>::iterator it1;
for (it1 = ret.first; it1 != ret.second; ++it1)
{
it1->second->newMessage(msg);
}
}
}
private:
multimap<string, Subscriber *> m_routingMap;
};
int main(int argc, char *argv[])
{
Sender sndr;
BaseMsg baseMsg;
Message message;
printf("Base Register\n");
Subscriber1 recv1;
sndr.registerForMsg(&recv1, baseMsg);
printf("Child Register\n");
Subscriber2 recv2;
sndr.registerForMsg(&recv2, message);
printf("Base call\n");
sndr.send(baseMsg); // I want only recv1 to receive this message
printf("Der. call\n");
sndr.send(message); // I want both Receivers to receive this message, but only recv2 will receive it
return 0;
}
8_0_for_Desktop_-
MinGW_Qt_SDK__Release\release\asdf.exe...
Базовый регистр
Регистрация: BaseMsg
Дочерний регистр
Регистрация: Сообщение
Базовый вызов
Триггер: BaseMsg
virtual void Subscriber1::newMessage(const BaseMsg&)
Der. call
Триггер: BaseMsg
virtual void Subscriber1::newMessage(const BaseMsg&)
Триггер: Message
virtual void Subscriber2::newMessage(const BaseMsg&)
C:\Users\David\Downloads \asdf-build-desktop-Qt
#include <string>
#include <vector>
#include <map>
#include <stdio.h>
using namespace std;
class BaseMsg
{
public:
BaseMsg()
{
theRealInit();
}
//incase you don't want to go all the way down the rabbit hole.
//At the bottom they are the same
virtual vector<string> const & registrationEntries() const {return m_SubClassChain;}
virtual vector<string> const & triggerEntries() const {return m_SubClassChain;}
protected:
virtual void init() { printf("Should NOT CALL THIS HERE!");}
vector<string> m_SubClassChain;
private:
void theRealInit()
{
m_SubClassChain.push_back("BaseMsg");
}
};
class Message : public BaseMsg
{
public:
Message() : BaseMsg()
{
init(); //MUST BE CALLED from child
}
virtual vector<string> const & triggerEntries() const {return m_TriggerEntries;}
protected:
virtual void init()
{
//BaseMsg::init();
m_SubClassChain.push_back("Message");
m_TriggerEntries.push_back("Message");
}
private:
vector<string> m_TriggerEntries;
};
class Subscriber
{
public:
virtual void newMessage(BaseMsg const & i_msg)
{
printf("%s\n", __PRETTY_FUNCTION__);
}
};
class Subscriber2 : public Subscriber
{
public:
virtual void newMessage(BaseMsg const & i_msg)
{
printf("%s\n", __PRETTY_FUNCTION__);
}
};
class Subscriber1 : public Subscriber
{
public:
virtual void newMessage(BaseMsg const & i_msg)
{
printf("%s\n", __PRETTY_FUNCTION__);
}
};
class Sender
{
//typdef vector<Receiver const & > Receivers;
public:
void registerForMsg(Subscriber * someoneThatCares, BaseMsg const & msg)
{
vector<string> const & triggers = msg.triggerEntries();
vector<string>::const_iterator it = triggers.begin();
for(; it != triggers.end(); it++)
{
printf("Registration: %s\n", it->c_str());
m_routingMap.insert(pair<string, Subscriber *>(*it, someoneThatCares));
}
}
void send(BaseMsg const & msg)
{
vector<string> const & triggers = msg.registrationEntries();
vector<string>::const_iterator it = triggers.begin();
for(; it != triggers.end(); it++)
{
printf("Trigger: %s\n", it->c_str());
pair<multimap<string, Subscriber *>::iterator, multimap<string, Subscriber *>::iterator> ret;
//borrowed from: http://www.cplusplus.com/reference/stl/multimap/equal_range/
ret = m_routingMap.equal_range(*it);
multimap<string, Subscriber *>::iterator it1;
for (it1 = ret.first; it1 != ret.second; ++it1)
{
it1->second->newMessage(msg);
}
}
}
private:
multimap<string, Subscriber *> m_routingMap;
};
int main(int argc, char *argv[])
{
Sender sndr;
BaseMsg baseMsg;
Message message;
printf("Base Register\n");
Subscriber1 recv1;
sndr.registerForMsg(&recv1, baseMsg);
printf("Child Register\n");
Subscriber2 recv2;
sndr.registerForMsg(&recv2, message);
printf("Base call\n");
sndr.send(baseMsg); // I want only recv1 to receive this message
printf("Der. call\n");
sndr.send(message); // I want both Receivers to receive this message, but only recv2 will receive it
return 0;
}
8_0_for_Desktop_-
MinGW_Qt_SDK__Release\release\asdf.exe завершился с кодом 0
#include <string>
#include <vector>
#include <map>
#include <stdio.h>
using namespace std;
class BaseMsg
{
public:
BaseMsg()
{
theRealInit();
}
//incase you don't want to go all the way down the rabbit hole.
//At the bottom they are the same
virtual vector<string> const & registrationEntries() const {return m_SubClassChain;}
virtual vector<string> const & triggerEntries() const {return m_SubClassChain;}
protected:
virtual void init() { printf("Should NOT CALL THIS HERE!");}
vector<string> m_SubClassChain;
private:
void theRealInit()
{
m_SubClassChain.push_back("BaseMsg");
}
};
class Message : public BaseMsg
{
public:
Message() : BaseMsg()
{
init(); //MUST BE CALLED from child
}
virtual vector<string> const & triggerEntries() const {return m_TriggerEntries;}
protected:
virtual void init()
{
//BaseMsg::init();
m_SubClassChain.push_back("Message");
m_TriggerEntries.push_back("Message");
}
private:
vector<string> m_TriggerEntries;
};
class Subscriber
{
public:
virtual void newMessage(BaseMsg const & i_msg)
{
printf("%s\n", __PRETTY_FUNCTION__);
}
};
class Subscriber2 : public Subscriber
{
public:
virtual void newMessage(BaseMsg const & i_msg)
{
printf("%s\n", __PRETTY_FUNCTION__);
}
};
class Subscriber1 : public Subscriber
{
public:
virtual void newMessage(BaseMsg const & i_msg)
{
printf("%s\n", __PRETTY_FUNCTION__);
}
};
class Sender
{
//typdef vector<Receiver const & > Receivers;
public:
void registerForMsg(Subscriber * someoneThatCares, BaseMsg const & msg)
{
vector<string> const & triggers = msg.triggerEntries();
vector<string>::const_iterator it = triggers.begin();
for(; it != triggers.end(); it++)
{
printf("Registration: %s\n", it->c_str());
m_routingMap.insert(pair<string, Subscriber *>(*it, someoneThatCares));
}
}
void send(BaseMsg const & msg)
{
vector<string> const & triggers = msg.registrationEntries();
vector<string>::const_iterator it = triggers.begin();
for(; it != triggers.end(); it++)
{
printf("Trigger: %s\n", it->c_str());
pair<multimap<string, Subscriber *>::iterator, multimap<string, Subscriber *>::iterator> ret;
//borrowed from: http://www.cplusplus.com/reference/stl/multimap/equal_range/
ret = m_routingMap.equal_range(*it);
multimap<string, Subscriber *>::iterator it1;
for (it1 = ret.first; it1 != ret.second; ++it1)
{
it1->second->newMessage(msg);
}
}
}
private:
multimap<string, Subscriber *> m_routingMap;
};
int main(int argc, char *argv[])
{
Sender sndr;
BaseMsg baseMsg;
Message message;
printf("Base Register\n");
Subscriber1 recv1;
sndr.registerForMsg(&recv1, baseMsg);
printf("Child Register\n");
Subscriber2 recv2;
sndr.registerForMsg(&recv2, message);
printf("Base call\n");
sndr.send(baseMsg); // I want only recv1 to receive this message
printf("Der. call\n");
sndr.send(message); // I want both Receivers to receive this message, but only recv2 will receive it
return 0;
}
person
David D
schedule
22.03.2012