接收广播消息的接口,同时又自己能请求广播
class IBroadcastEvent
{
public:
friend class Broadcaster;
IBroadcastEvent() :broadcaster(nullptr){}
virtual void recvMessage(const std::string& msg) = 0;
virtual void requestBroadcast(const std::string& msg)
{
if (broadcaster)
{
broadcaster->sendBroadcastMessage(msg);
}
}
protected:
Broadcaster* broadcaster;
};
发送广播对象
//Header
class Broadcaster
{
public:
Broadcaster(){}
~Broadcaster(){ recver_list.clear(); }
void sendBroadcastMessage(const std::string& msg);
bool operator +=(IBroadcastEvent*);
bool operator -=(IBroadcastEvent*);
inline size_t getCount()const{ return recver_list.size(); }
private:
std::set<IBroadcastEvent*> recver_list;
void detachMsg(IBroadcastEvent*, const std::string& );
std::mutex protect_mutex;
};
//Source
bool Broadcaster::operator+=(IBroadcastEvent* e)
{
if (e)
{
std::lock_guard<std::mutex> lck(protect_mutex);
recver_list.insert(e);
e->broadcaster = this;
return true;
}
return false;
}
bool Broadcaster::operator-=(IBroadcastEvent* e)
{
std::lock_guard<std::mutex> lck(protect_mutex);
recver_list.erase(e);
e->broadcaster = nullptr;
return true;
}
void Broadcaster::sendBroadcastMessage(const std::string& msg)
{
for (std::set<IBroadcastEvent*>::iterator iter = recver_list.begin(); iter != recver_list.end(); iter++)
{
detachMsg(*iter, msg);
}
}
void Broadcaster::detachMsg(IBroadcastEvent* e, const std::string& msg)
{
e->recvMessage(msg);
}
测试
class Listen : public IBroadcastEvent
{
public:
Listen(std::string name) :instance_name(name){}
void recvMessage(const std::string& msg)
{
cout <<instance_name<<"----->"<< msg << endl;
}
private:
std::string instance_name;
};
class Scan : public IBroadcastEvent
{
public:
void recvMessage(const std::string& msg)
{
cout<<"I'm a scan ,I recv msg:"<< msg << endl;
}
};
int main()
{
Broadcaster br;
Listen le0("0");
Listen le1("1");
Listen le2("2");
Listen le3("3");
br += &le0;
br += &le1;
br += &le1;
br += &le1;
br += &le2;
br += &le3;
int a = 123;
br.sendBroadcastMessage("hello");
cout << "==========================================\n";
br -= &le2;
string ss = "123456";
Scan s;
br += &s;
br.sendBroadcastMessage("hi");
s.requestBroadcast("request");
getchar();
return 0;
}
结果
-
3----->hello
2----->hello
1----->hello
0----->hello
==========================================
I'm a scan ,I recv msg:hi
3----->hi
1----->hi
0----->hi
I'm a scan ,I recv msg:request
3----->request
1----->request
0----->request
注意事项
Broadcaster 和 IBroadcastEvent是相互调用的,并且使用了类成员函数,c++中提供类的前项申明但是不提供类的成员函数申明,所以为了避免矛盾,将两个类分在两个文件中,注意其中一个通过头文件申明,另一个使用前项申明,在实现文件中包含头文件。
举例:
// a.h
#include "b.h"//使用头文件申明
class A
{
public:
A();
private:
B b;
};
// a.cpp
#include "a.h"
A::A(){}
// b.h
class A;//类前项申明
class B
{
public:
void print(A *);
};
//b.cpp
#include "a.h"
#include "b.h"
void B::print(A *a)
{
;
}