首页 > 解决方案 > 如何创建 shared_ptr 的容器到抽象类

问题描述

我正在尝试在 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)创建抽象类时出现错误:

错误:抽象类类型'Observer'的无效新表达式</p>

我试过shared_ptr<Observer<T>> observerPtr(observer)了,但效果不佳:

错误:没有匹配函数调用 'std::shared_ptr >::shared_ptr(Observer&)'</p>

如何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
}

标签: c++c++14shared-ptr

解决方案


要回答有关实现 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>>as 参数addObserver(shared_ptr<Observer<T>>& o)。如果您必须使用addObserver(Observer<T>&)接口并且希望“观察者”设置为共同管理观察者对象的生命周期,则可以使用 std::enable_shared_from_this 并使 Observer 成为 std::enable_shared_from_this 的子类。

希望这可以帮助。


推荐阅读