測試環境:visual studio 2017。
測試參數:標準符合:C++ 14 和 C++ 17
理論上也符合C++ 11。
EventWrap實現的是主題類(發佈者)
Observer的派生類是觀察者。
這個實現新穎的部分是:
1、類的特種函數的定義向C++新標準靠攏。自定義析構函數後(支持虛析構),添加移動操作函數(支持移動操作),添加冗餘的複製操作函數(新標準推薦的做法)。
2、採用智能指針。如果某個觀察者類銷燬,主題類能自動感知到,不進行消息發佈。智能指針的使用也保證某個觀察者對象執行Update期間this指針有效(在多線程環境下,它可能被銷燬導致this失效。)。當然目前這份源碼不會在多線程使用,還沒有保護observers_變量。
#include "pch.h"
#include <iostream>
#include <memory>
#include <list>
#include <string>
#include <chrono>
using namespace std;
using namespace std::chrono;
class EventPara
{
public:
string name_;
};
class Observer
{
public:
virtual void Update(EventPara para) = 0;
public:
//按照C++標準的解釋,類中沒有用戶聲明的構造函數時編譯器生成默認構造函數。
//在visual studio 2017運行時,因爲聲明瞭複製構造函數或賦值構造函數,導致編譯器沒有生成默認構造函數。
//文檔中認爲這兩個函數不屬於構造函數,所以測試結果和文檔解釋存在衝突。
Observer() = default;
//虛析構保證子類析構
virtual ~Observer() = default;
//C++不推薦聲明析構函數而不聲明覆制操作
Observer(const Observer&) = default;
Observer& operator=(const Observer&) = default;
//聲明瞭析構函數後,編譯器不默認生成移動操作函數
Observer(Observer&&) = default;
Observer& operator = (Observer&&) = default;
};
class Student : public Observer
{
public:
void Update(EventPara para) override
{
cout << "Student " << this << para.name_ << endl;
}
};
class Teacher : public Observer
{
public:
void Update(EventPara para) override
{
cout << "Teacher " << this << para.name_ << endl;
}
};
class EventWrap
{
public:
void Register(weak_ptr<Observer> o)
{
observers_.emplace_back(o);
}
void Publish(EventPara& para)
{
for (auto& p : observers_)
{
auto ob = p.lock();
if (ob)
{
ob->Update(para);
}
}
observers_.remove_if([](weak_ptr<Observer>& o)
{
if (o.expired())
{
return true;
}
return false;
});
}
int Count()
{
return observers_.size();
}
private:
list<weak_ptr<Observer>> observers_;
};
int main()
{
EventWrap e;
EventPara para;
{
shared_ptr<Student> stu1 = make_shared<Student>();
shared_ptr<Student> stu2 = make_shared<Student>();
shared_ptr<Teacher> tea1 = make_shared<Teacher>();
e.Register(stu1);
e.Register(stu2);
e.Register(tea1);
para.name_ = " 動態生成的參數:" + to_string(steady_clock::now().time_since_epoch().count());
cout << e.Count() << endl;
e.Publish(para);
cout << e.Count() << endl;
}
shared_ptr<Student> stu3 = make_shared<Student>();
shared_ptr<Teacher> tea2 = make_shared<Teacher>();
e.Register(stu3);
e.Register(tea2);
para.name_ = " 動態生成的參數:" + to_string(steady_clock::now().time_since_epoch().count());
cout << e.Count() << endl;
e.Publish(para);
cout << e.Count() << endl;
return 0;
}
執行結果: