简体   繁体   English

如何在不是shared_ptr的成员中使用shared_ptr?

[英]How to use shared_ptr in a member which is not a shared_ptr?

I'm working on a couple of classes and I'm wondering how I can use a normal member in my application class, where the member needs to use shared_from_this()? 我正在研究几个类,我想知道如何在我的应用程序类中使用普通成员,该成员需要使用shared_from_this()?

Here is some code to clarify what I mean (see comments) 这是一些代码来阐明我的意思(请参阅评论)

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.
    }
};

You have three solutions to this problem: 您有以下三种解决方案:

First solution : force the application to create a shared_ptr by making its constructor private. 第一个解决方案 :通过将其构造函数设为私有来强制应用程序创建一个shared_ptr。 This is what I would recommend to do for any class that derivates from enable_shared_from_this 对于任何从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()) ;
    }
};

Second solution : change your code design. 第二种解决方案 :更改您的代码设计。 You should not ask the ApplicationModel to register itself to the Observable, but do it yourself. 您不应该要求ApplicationModel将自身注册到Observable,而是自己进行。 This way the ApplicationModel doesn't enforce anything, but if its owner wants to call addObservable , it has to create a shared_ptr. 这样, ApplicationModel不会强制执行任何操作,但是如果其所有者想要调用addObservable ,则必须创建一个shared_ptr。 This is more or less what is called dependency injection . 这或多或少就是所谓的依赖注入

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

EDIT: Third solution: use a dummy shared_ptr, like this: 编辑:第三个解决方案:使用虚拟的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());
    }
};

The idea is to create a shared_ptr to this and to tell shared_ptr not to call the destructor (here I use an empty lambda function but you can easily create an inline structure). 我们的想法是创建一个shared_ptr来this并告诉shared_ptr不调用析构函数(这里我用一个空的lambda函数,但你可以很容易地创建一个内联结构)。 This is a hack and you shouldn't do so. 这是黑客,您不应该这样做。

You can't. 你不能 shared_from_this() requires that your object be allocated dynamically via a shared_ptr . shared_from_this()要求通过shared_ptr动态分配对象。

See this page of the documentation , which states: 请参阅文档的此页面 ,其中指出:

Requires: enable_shared_from_this must be an accessible base class of T. *this must be a subobject of an instance t of type T . 要求:enable_shared_from_this必须是T的可访问基类。*这必须是类型T的实例t的子对象。 There must exist at least one shared_ptr instance p that owns t. 必须至少存在一个拥有t的shared_ptr实例p。

So you would need to alter your code to have any instances of ApplicationModel be "owned" by a shared_ptr. 因此,您需要更改代码,以使ApplicationModel任何实例都由shared_ptr“拥有”。 For example: 例如:

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;  
    //...
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM