Reputation: 502
I want to generate a shared_ptr from a class and use it instead of the this* raw pointer to initialize another one. The other expects a shared_ptr in Constructor. I'm showing only a excerpt:
class Soundfile : std::enable_shared_from_this<Soundfile> { ...more code
std::shared_ptr<Soundfile> Soundfile::getptr() {
return shared_from_this();
}
I need to initialize another class called Channel inside from Soundfile:
bool Soundfile::openRead(const char *filename_) {
//more code ...
channels = std::make_shared<Channel>(getptr() , windowSize_, gdata);
}
This doesn't works, I become a weak_ptr exception, I tried to do the following:
std::shared_ptr<Soundfile> Soundfile::getptr() {
try {
return shared_from_this();
}
catch (const std::bad_weak_ptr&) {
return std::make_shared<Soundfile>();
}
}
This works, but I become a new empty shared_ptr, I saved previously data inside the class Soundfile, I need to use it inside Channel, for this reason that is not what I'm looking for. I searched for a solution here, but I couldn't find one, sorry if the question is duplicated
EDIT: Here is a minimal example what I'm trying to explain:
class A : std::enable_shared_from_this<A> {
public:
A() {}
~A() {}
std::shared_ptr<A> getptr() {
return shared_from_this();
}
void my_method() {
myB = std::make_shared<B>(getptr());
}
private:
std::shared_ptr<B> myB;
};
class B {
public:
B(std::shared_ptr<A> _myA) {
myA = _myA;
}
~B() {}
private:
std::shared_ptr<A> myA;
};
int main() {
std::shared_ptr<A> myA = std::make_shared<A>();
myA->my_method();
}
Upvotes: 0
Views: 161
Reputation: 4118
std::enable_shared_from_this::shared_from_this
only works if the instance is currently managed by a shared pointer.
You can think of enable_shared_from_this
as a class that contains a weak_ptr
. When passing an instance of a class that is derived from std::enable_shared_from_this
to the shared_ptr
constructor, that constructor will initialize the weak_ptr
inside it. Calling shared_from_this
will only work after the weak pointer has been initialized, because it is implemented by converting that weak_ptr
to a shared_ptr
.
If you call shared_from_this
before the weak_ptr
has been initialized, it will raise a bad_weak_ptr
exception, because the cast to a shared_ptr
fails.
In order to solve your problem, you have to make sure that any instance of Soundfile is managed by a shared_ptr
before the getptr()
method or any method calling it is called.
In those rare cases were I use shared_from_this
, I usually make the constructors private and add static factory methods in order to enforce this:
class A {
public:
static std::shared_ptr<A> create() {
return std::make_shared<A>();
}
private:
A();
};
You still have to be careful what you are doing in your constructors, because shared_from_this
won't work inside them.
Upvotes: 4