簡體   English   中英

如何創建shared_ptr的容器到抽象類

[英]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#可以很容易忽略的壽命ObserverSubject ,事情會(主要)是好的。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM