【发布时间】:2023-03-12 00:36:01
【问题描述】:
我正在尝试编写简单的父子类,并尝试使用智能指针。
听说在构造函数中使用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。
【问题讨论】:
-
将
protected enable_shared_from_this<Base>更改为public enable_shared_from_this<Base>,然后您将看到所需的输出。 LIVE DEMO. -
开启警告;这段代码有很多问题。您可能希望使用“密码习语”使构造函数有效地私有化,并在类中提供静态工厂函数(否则人们可能会在堆栈上创建非共享对象或
new建立自己的非共享对象,并且该对象是自我感知的,它应该被共享)。 stackoverflow.com/questions/52179063/…
标签: c++ smart-pointers