为什么weak_from_this()总是返回空的弱指针?

时间:2019-06-02 12:50:03

标签: c++ smart-pointers

我正在尝试编写简单的父子类,并尝试为其使用智能指针。

我听说在构造函数中使用shared_from_this()是不好的,所以我将其放在connect()方法中。但是,当我在此方法中调用weak_from_this()时,它将返回空的弱指针。

我不知道我在做什么错,请帮忙:)

#include <iostream>
#include <memory>
#include <list>
#include <sstream>

using namespace std;

class Base : protected enable_shared_from_this<Base> {
public:
    weak_ptr<Base> parent;

    virtual void connect() {}
    virtual void replaceChild(shared_ptr<Base> oldChild, shared_ptr<Base> newChild) {}

    void setParent(weak_ptr<Base> parent) {
        this->parent = parent; // <-- passed to here, but always empty
    }

    virtual string toString() { return "Base"; }
};

class Item : public Base {
public:
    string toString() { return "Item"; }
};

class Item2 : public Base {
public:
    void connect() {
        if (auto parent = this->parent.lock()) {
            parent->replaceChild(this->shared_from_this(), make_shared<Item>());
        }
    }

    string toString() { return "Item2"; }
};

class Container : public Base {
public:
    list<shared_ptr<Base>> items;

    void connect() {
        for (auto &item : items) {
            weak_ptr<Base> ptr = this->weak_from_this();
            item->setParent(ptr); // <-- ptr is empty here, according to debugger breakpoint
            item->connect();
        }
    }

    void replaceChild(shared_ptr<Base> oldChild, shared_ptr<Base> newChild) {
        for (auto &item : items) {
            if (item == oldChild) {
                item = newChild;
                item->setParent(this->weak_from_this());
                item->connect();
                break;
            }
        }
    }

    string toString() {
        ostringstream ss;
        ss << "Container(";
        for (auto item : items) {
            if (item != *items.begin()) ss << ", ";
            ss << item->toString();
        }
        ss << ")";
        return ss.str();
    }
};

int main(int argc, char ** argv) {
    shared_ptr<Base> base = make_shared<Container>();

    if (auto cont1 = dynamic_pointer_cast<Container>(base)) {
        cont1->items.push_back(make_shared<Item2>());
        cont1->items.push_back(make_shared<Base>());
        cont1->items.push_back(make_shared<Container>());
    }

    base->connect();

    cout << base->toString() << endl;

    return 0;
}

预期输出:

Container(Item, Base, Container())

实际输出:

Container(Item2, Base, Container())

因为Item2具有空的parent

1 个答案:

答案 0 :(得分:0)

感谢@ rafix07 !!! 从protected更改为public,它可以正常工作!!!