Как использовать shared_ptr в члене, который не является shared_ptr? - PullRequest
0 голосов
/ 30 сентября 2010

Я работаю над парой классов и мне интересно, как я могу использовать нормальный член в своем классе приложения, где член должен использовать shared_from_this ()?

Вот некоторый код дляуточнить, что я имею в виду (см. комментарии)

class Observable {
public:
    void addObserver(boost::shared_ptr<Observer> observer) {
        // add to a list
    }
};

class Observer {
public:
    virtual void onUpdate() = 0;
};

class MyObservableType : public Observable {
};

class ApplicationModel : public Observer {
private:
    MyObservableType mot;
public:
    void setup() {
    // how do I pass this as a boost::shared_ptr, as ApplicationModel is not 
    // a boost::shared_ptr in the Application class this using a call to 
    // "shared_from_this()" (and inheriting public shared_from_this<ApplicationModel>
        mot.addObserver([shared_from_this]) 
    }
};

class Application {
private:
    ApplicationModel model;
public:
    void setup() {
        model.
    }
};

Ответы [ 2 ]

1 голос
/ 30 сентября 2010

У вас есть три решения этой проблемы:

Первое решение : заставить приложение создать shared_ptr, сделав его конструктор закрытым. Это то, что я бы порекомендовал сделать для любого класса, производного от enable_shared_from_this

class ApplicationModel : public Observer, public boost::enable_shared_from_this<ApplicationModel> {
private:
    ApplicationModel(); // private constructor

    MyObservableType mot;
public:
    // an instance of this class can only be created using this function
    static boost::shared_ptr<ApplicationModel> buildApplicationModel() {
        return boost::make_shared<ApplicationModel>();
    }

    void setup() {
        mot.addObserver(shared_from_this()) ;
    }
};

Второе решение : измените дизайн кода. Вы не должны просить ApplicationModel зарегистрироваться в Observable, а делать это самостоятельно. Таким образом, ApplicationModel ничего не навязывает, но если его владелец хочет вызвать addObservable, он должен создать shared_ptr. Это более или менее то, что называется внедрение зависимости .

class Application {
private:
    boost::shared_ptr<ApplicationModel> model;
    MyObservableType mot;
public:
    void setup() {
        model = boost::make_shared<ApplicationModel>();
        mot.addObserver(model);
    }
};

РЕДАКТИРОВАТЬ: Третье решение: использовать фиктивный shared_ptr, как это:

class ApplicationModel : public Observer {
private:
    boost::shared_ptr<ApplicationModel> myself;

    MyObservableType mot;

public:
    void setup() {
        mot.addObserver(myself) ;
    }

    ApplicationModel() {
        myself = boost::shared_ptr<ApplicationModel>(this, [](ApplicationModel*) {});
    }

    ~ApplicationModel() {
        mot.removeObserver(myself);
        assert(myself.unique());
    }
};

Идея состоит в том, чтобы создать shared_ptr для this и указать shared_ptr не вызывать деструктор (здесь я использую пустую лямбда-функцию, но вы можете легко создать встроенную структуру). Это взлом, и вы не должны этого делать.

0 голосов
/ 30 сентября 2010

Вы не можете.shared_from_this() требует, чтобы ваш объект выделялся динамически через shared_ptr.

. См. эту страницу документации , в которой говорится:

Требуется: enable_shared_from_thisдолжен быть доступным базовым классом T. * это должен быть подобъект экземпляра t типа T.Должен существовать, по крайней мере, один экземпляр shared_ptr p, которому принадлежит t.

Так что вам нужно будет изменить свой код, чтобы все экземпляры ApplicationModel были «принадлежат» shared_ptr.Например:

class ApplicationModel : 
    public Observer,
    public boost::enable_shared_from_this<ApplicationModel>
{
    //...
    void setup() {
        mot.addObserver(shared_from_this());
    }
};

class Application {
private:
    // Application object must initialize this somewhere
    boost::shared_ptr<ApplicationModel> model;  
    //...
};
...