[英]how to create a container of shared_ptr to abstract class
我正在嘗試用 C++ 創建一個主題觀察者系統,就像 C# 中的事件系統一樣。 觀察者類:
template <class T>
class Observer {
int id;
public:
static int nextId;
Observer() : id(nextId++) {}
virtual void handleEvent(const T&) = 0;
virtual ~Observer();
};
學科類:
template<class T>
class Subject {
set<shared_ptr<Observer<T>>> observers;
public:
Subject() : observers() {}
void notify(const T&);
void addObserver(Observer<T>& );
void removeObserver(Observer<T>&);
Subject<T>& operator+=(Observer<T>&);
Subject<T>& operator-=(Observer<T>&);
Subject<T>& operator()(const T&);
};
問題是當我嘗試實現addObserver
我不知道如何將引用添加到集合中。
我知道make_shared<Observer<T>>
正在創建一個新實例,所以當我嘗試make_shared<Observer<T>>(observer)
我嘗試創建一個抽象類時出錯:
錯誤:抽象類類型“觀察者”的新表達式無效
我試過shared_ptr<Observer<T>> observerPtr(observer)
,但效果不佳:
錯誤:沒有匹配的函數調用'std::shared_ptr >::shared_ptr(Observer&)'
如何根據從抽象類派生的對象的引用創建shared_ptr
?
我想要實現的是讓這個例子工作:
class TemperatureSensor : public Subject<int> {};
class AirConditioner : public Observer<int> {
static int nextId;
int id;
void onTemperatureChange(int temperature){
std::cout << "Air Conditioner #" << id << " got a report from TemperatureSensor, reading " << temperature << std::endl;
}
public:
AirConditioner() : Observer() {
id = (++nextId);
}
void handleEvent(const int& param) override {
onTemperatureChange(param);
}
};
int AirConditioner::nextId = 0;
int main(){
TemperatureSensor s;
AirConditioner a,b,c;
(((s += a) += b) += c);
s(42); // Should print:
// Air Conditioner #1 got a report from TemperatureSensor, reading 42
// Air Conditioner #2 got a report from TemperatureSensor, reading 42
// Air Conditioner #3 got a report from TemperatureSensor, reading 42
}
要回答有關實現 addObserver 的問題,使其工作的最簡單方法是將指針存儲在容器中:
template<class T>
class Subject {
set<Observer<T>*> observers;
public:
Subject() : observers() {}
void addObserver(Observer<T>& o) { observers.insert(&o); }
根據您希望如何管理觀察者對象的生命周期,您可以使用set<shared_ptr<Observer<T>>>
,但在這種情況下,您應該將share_ptr<Observer<T>>
作為參數傳遞給addObserver(shared_ptr<Observer<T>>& o)
。 如果您必須使用addObserver(Observer<T>&)
接口並且您希望“觀察者”設置為共同管理觀察者對象的生命周期,您可以使用 std::enable_shared_from_this 並使 Observer 成為 std:: 的子類enable_shared_from_this。
希望這可以幫助。
如何根據從抽象類派生的對象的引用創建 shared_ptr?
一般來說,你不能。 指向抽象基類的共享指針只能指向具體實例。 您通常無法在編譯時通過基本引用知道具體類型。
您可能應該更改接口,以便函數接受共享指針作為參數,而不是引用。
如何根據從抽象類派生的對象的引用創建 shared_ptr?
您不能為抽象類創建 shared_ptr。
但是你可以做一些事情來完成代碼工作。
一個可能的解決方案是定義基類Observer而不是 abstrastct ,刪除=0
。 然后為了確保您不會在基類 Observer 上以一種糟糕的方式調用實際的純虛函數,您可以在基類 Observer 的方法的實現中拋出異常。 因此,當在Observer類上調用時它會引發異常,在另一種情況下(例如在AirConditioner類中),它會在不引發異常的情況下完成其工作。
注意:這只是這種情況的一種解決方法,請嘗試重新考慮您的代碼設計以獲得更好的實現
C#可以很容易忽略的壽命Observer
的Subject
,事情會(主要)是好的。 C++ 不允許您忽略生命周期。
如果Subject
應該讓所有Observer
保持活動狀態,那么您需要傳遞std::shared_ptr<Observer>
,而不是Observer &
。
如果您確定您的Observer
總是比您的Subject
removeObserver
長,或者總是可以在它們死之前調用removeObserver
,那么您仍然可以傳遞Observer &
,並存儲std::reference_wrapper<Observer>
。
如果您的所有Observer
都歸std::shared_ptr
擁有,但您不希望Subject
影響它們的生命周期,請傳遞並存儲std::weak_ptr<Observer>
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.