在基类中使用shared_from_this时,C ++抛出bad_weak_ptr

时间:2014-03-11 09:43:12

标签: c++11 shared-ptr weak-ptr

我打算实现一个线程安全的观察者模式。但是在测试下面的代码时我得到了一个coredump:

要运行代码,只需编译: g ++ --std = c ++ 11 code.cpp

请帮助我找到其中发生的问题:

#include <memory>
#include <vector>
#include <mutex>
#include <algorithm>
#include <iostream>

class Observable;
class CurrentConditionDisplay;

class Observer : std::enable_shared_from_this<Observer> {
public:
    void observe(Observable* s);
    virtual ~Observer() ;
    virtual void update(float temp, float humidity, float pressure) = 0; 

private:
    Observable *sub_;
};

class Observable {
protected :
    class MutexGuard {
    public:
        MutexGuard(std::mutex* mtx) : gmtx_(mtx) {
            this->lock();
        }
        void lock () const {
            gmtx_->lock();
        }
        void unlock () const {
            gmtx_->unlock();
        }
        ~MutexGuard() {
            this->unlock();
        }
    private:
        std::mutex* gmtx_ ;
    };
#define MutextGuard(x) error "Missing Guard Obect" 

public:

    typedef std::weak_ptr<Observer> ObWeakPtr;
    typedef std::shared_ptr<Observer> ObSharedPtr; 

    virtual ~Observable() {
        oblist_.clear();
    } 

    void registerObserver(std::weak_ptr<Observer> ob);
    //void removeObserver(std::weak_ptr<Observer> ob);
    void notifyObservers();

protected:
    virtual void notify(std::shared_ptr<Observer> sptr) = 0;
    typedef std::vector<std::weak_ptr<Observer>> ObList;
    ObList oblist_;

    std::mutex mtx_;
};

void Observer::observe(Observable* s) {
    sub_ = s;
    sub_->registerObserver(shared_from_this());
}
Observer::~Observer() {
//    sub_->removeObserver(shared_from_this());
}


void Observable::notifyObservers() {
    MutexGuard m(&mtx_);
    for (ObList::iterator it = oblist_.begin(); 
        it != oblist_.end(); ++it) {
        std::shared_ptr<Observer> sptr = it->lock();
        if (sptr) {
            this->notify(sptr);
        } else {
            oblist_.erase(it); 
        }
    }       
}

void Observable::registerObserver(std::weak_ptr<Observer> ob) {
    MutexGuard m(&mtx_);
    //if (oblist_.end() 
    //    != std::find (oblist_.begin(), oblist_.end(), ob)) {
        oblist_.push_back(ob);
    //}
}
/*
void Observable::removeObserver(std::weak_ptr<Observer> ob) {
    MutexGuard m(&mtx_);
    ObList::iterator it = oblist_.end();
    if ( oblist_.end() != 
        (it = std::find(oblist_.begin(), oblist_.end(), ob)) ) {
        oblist_.erase(it);
    }
}*/

class WeatherData : public Observable {
public:
    void measurementsChanged(float temp, float humi, float pres) {
        bool changed = false;
        temp_ == temp ? temp_ = temp, changed |= true : 1;
        humi_ == humi ? humi_ = humi, changed |= true : 1;
        pres_ == pres ? pres_ = pres, changed |= true : 1;
        if (changed) {
            this->notifyObservers();
        }
    }

    void notify(std::shared_ptr<Observer> sptr) {
        sptr->update(temp_, humi_, pres_);
    }

private:
    float temp_; // temperature
    float humi_; // humidity
    float pres_; // pressure
};

class CurrentConditionDisplay : public Observer {
public:
    void update(float temp, float humi, float pres) {
        temp_ = temp;
        humi_ = humi;
        display();
    }

    void display() {
        std::cout << "Current Condition: " << temp_ 
            << "'F degrees and " << humi_ << "\% humidity";
    }

private:
    float temp_;
    float humi_;
};

int main() {

    WeatherData* w = new WeatherData();
    CurrentConditionDisplay * cur = new CurrentConditionDisplay();
    cur->observe(w);

    w->measurementsChanged(1.0, 1.0, 1.0);
    return 0;    
}

1 个答案:

答案 0 :(得分:2)

这是问题所在:

CurrentConditionDisplay * cur = new CurrentConditionDisplay();

要使用shared_from_this(),对象必须由shared_ptr拥有,但您的对象不是。

您应该使用:

auto cur = std::make_shared<CurrentConditionDisplay>();