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

Why weak_from_this() always returns empty weak pointer?

本文关键字:返回 指针 from weak this 为什么      更新时间:2023-10-16

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

我听说在构造函数中使用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.

感谢@rafix07!!!更改为protected public,它有效!!