I'm trying to write simple parent-child classes, and trying to use smart pointers for it.
I heard that it's bad to use shared_from_this()
in constructors, so i put it in connect()
method. But when i call weak_from_this()
in this method, it returns empty weak pointer.
I have no idea what i'm doing wrong, please help:)
#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;
}
Expected output:
Container(Item, Base, Container())
Actual output:
Container(Item2, Base, Container())
because Item2
has empty parent
.