I have a class MyClass that should be able to return this wrapped in QSharedPointer<MyClass>.
It is my understanding (and experience) that simply creating new instances of QSharedPointer<MyClass>(this) is NOT the way to go. Instead The correct way to accomplish what I want is to let MyClass inherit from QEnableSharedFromThis<MyClass> to provide the member function sharedFromThis().
This member function should return this wrapped in QSharedPointer<MyClass> without all the bad side effects that would otherwise occur.
class MyClass : public QEnableSharedFromThis<MyClass>
{
/* ... */
public:
void testSharedThis()
{
auto sp=QEnableSharedFromThis<MyClass>::sharedFromThis();
if(sp.isNull()){
qWarning()<<"SHARED POINTER TO *this* WAS NULL!";
}
}
};
void main(){
MyClass *mc=new MyClass;
mc->testSharedThis();
}
However when I run testSharedThis() in the example above, sharedFromThis() always returns nullptr instead of this wrapped in QSharedPointer<MyClass>.
I am new to QEnableSharedFromThis and I am wondering if there is something that I am missing, or what could be the cause of this?
According to the official documentation:
A base class that allows obtaining a QSharedPointer for an object already managed by a shared pointer. You can inherit this class when you need to create a QSharedPointer from any instance of a class; for instance, from within the object itself.
So you need to instantiate your pointer as smart pointer:
QSharedPointer<MyClass> mc(new MyClass());
mc->testSharedThis();
Or in your case use the equivalent to std::make_shared for Qt Smart Pointers:
QSharedPointer<MyClass> mc = QSharedPointer<MyClass>::create();
mc->testSharedThis();
Related
I use a library that only returns references to created objects Entity& Create(int id). In my class, I need to create one of these and store it.
I had thought to use class member std::reference_wrapper<Entity> MyClass::m_Entity but the problem is, I would like to create this object in a call to a method like MyClass::InitEntity() – so I run into a compile error "no default constructor available" because m_Entity is not initialised in my constructor.
Is there any way around this, other than to change my class design? Or is this a case where using pointers would make more sense?
Is MyClass in a valid state if it doesn't have a valid reference to an Entity? If it is, then you should use a pointer. The constructor initializes the pointer to nullptr, and the InitEntity function assigns it to the address of a valid Entity object.
class MyClass
{
public:
MyClass(): _entity(nullptr) {}
void InitEntity() { _entity = &Create(123); }
void doSomethingWithEntity()
{
if (_entity) ...
}
private:
Entity *_entity;
};
If MyClass isn't in a valid state without a valid reference to an Entity, then you can use a std::reference_wrapper<Entity> and initialize it in the constructor.
class MyClass
{
public:
MyClass(): _entity(Create(123)) {}
void doSomethingWithEntity()
{
...
}
private:
std::reference_wrapper<Entity> _entity;
};
Of course which one you go with depends on how MyClass is supposed to be used. Personally, the interface for std::reference_wrapper is a little awkward for me, so I'd use a pointer in the second case as well (while still ensuring that it's always not null).
I have a certain type called A and I want to create multiple instances of std::unique_ptr<A, void(*)(A *ptr)> without explicitly passing the custom deleter every time. This is what I came up with:
void ADeleter(A *ptr) {
// custom deletion logic
}
class APtr : public std::unique_ptr<A, void(*)(A *ptr)> {
APtr() : APtr(nullptr) {}
APtr(A *ptr) : std::unique_ptr<A, void(*)(A *ptr)>(ptr, ADeleter) {}
};
Is it safe (or even a good practice) to inherit from std::unique_ptr (or other smart pointer classes) in order to abstract construction with a custom deleter?
No, the only classes in std:: you should inherit from have virtual destructors. The design of most of std is template parameters as extension points, rather than subclassing.
What you want instead is
struct ADeleter {
void operator()(A *ptr) {
// custom deletion logic
}
};
using APtr = std::unique_ptr<A, ADeleter>;
A problem that might ( but should never ) arise is that because std::unique_ptr doesn't have a virtual destructor you shouldn't call delete on an object that has as different dynamic type than the pointer that refers to it (for example, deleting APtr through a pointer of std::unique_ptr) because that's UB which would be ironic since smart pointers are there to stop raw new and delete in the first place.
Other than that, I see no immediate issue with your way.
You should not inherit from any class if you don't know if it has virtual destructor. Of course it can be done, but you have to be careful. It happens that unique_ptr don't have virtual destructor. So I suggest insted of inheritance use composition. Eg:
template<typename T>
class Ptr {
public:
//TODO: here provide all needed member functions for Ptr class.
private:
std::unique_ptr<A, void(*)(A *ptr)> ptr;
};
Note that your question is opinion based.
If you are going to use pointer with specific deleter in many places - why not. I don't see any issues with that.
One recommendation I can give - use callable class as a deleter. Your APtr instance takes 2 pointers: one to an object, another one to a deleter function. If you use separate empty class for deleter, the result will only take 1 pointer and will be able to avoid additional function call on destruction.
You don't need to subclass, you can just use a using directive as follows:
class MyClass; //defined elsewhere
struct MyClass_deleter
{
MyClass_deleter() = default;
void operator()(MyClass* object)
{
// delete or clean up object here
}
};
using MyClass_pointer = std::unique_ptr<MyClass, MyClass_deleter>;
// and use it as follows:
MyClass_pointer p(new MyClass());
You can do something like this:
template <typename T>
using unique_ptr_with_my_deleter = std::unique_ptr<T, my_deleter>;
//[...]
unique_ptr_with_my_deleter<int> u(new int(0));
Note that you need a C++11 compliant compiler for this to work.
I am trying the figure out a way to use shared_ptr and weak_ptr in my code. I have two classes - Class One and Class Two. Two in an inner class of One. Class two's constructor takes in a weak_ptr of Class One as shown below and stores it for later use.
Class One
{
Class Two
{
private:
std::weak_ptr<One> m_wptrOne;
public:
Two(std::weak_ptr<One> wptrOne)
{
m_wptrOne = wptrOne;
/* m_wptr is used later by class Two if not expired and valid ofcourse */
}
}; // End Class Two
.....
void foo()
{
std::shared_ptr sptrOne(this);
Two obj(sptrOne);
.... /* do my work */
} // Program crashes when foo terminates
}; //End Class One
I get a crash when my function foo returns because I think "sptr" is trying to free "this" pointer thinking that it is the only owner of it.
How can I solve this problem? Or is my program architecturally incorrect? Any suggestion would be greatly appreciated.
Thanks,
Tushar
I don't want to make it compulsory for my library users to create the object on the heap as a shared pointer.
Then your inner class cannot require a weak_ptr. The use of a weak_ptr requires the use of a shared_ptr; it relies on the machinery that shared_ptr creates to know when the pointer has been destroyed. So if you don't want users to have to use shared_ptr, you cannot do anything that expects the class to be wrapped in a shared_ptr. Like create a weak_ptr from it.
Therefore, you need to make your inner class independent of weak_ptr if you want users to be able to not create these objects on the heap.
You could try something where you force users to wrap their stack objects in a shared_ptr that uses a special deleter. But that'd be far more annoying than just heap allocating it.
The below is an example of using enable_shared_from_this to pass weak ownership semantics from this.
Note that it is not possible to express weak ownership semantics to an object with automatic storage duration.
The crash you mention regarding shared_from_this is probably an exception of type std::bad_weak_ptr caused by the attempt to gain a shared_ptr from an object that is not shared.
#include <memory>
class One : public std::enable_shared_from_this<One>
{
public:
class Two
{
private:
std::weak_ptr<One> m_wptrOne;
public:
Two(std::weak_ptr<One> wptrOne)
{
m_wptrOne = wptrOne;
/* m_wptr is used later by class Two if not expired and valid ofcourse */
}
}; // End Class Two
//.....
void foo()
{
std::shared_ptr<One> sptrOne = shared_from_this();
Two obj(sptrOne);
//.... /* do my work */
} // Program crashes when foo terminates
}; //End Class One
int main()
{
auto one = std::make_shared<One>();
one->foo();
}
I have one base class which holds a map for function pointers like this
typedef void (BaseClass::*event_t)();
class BaseClass {
protected:
std::map<std::string, event_t> events;
public:
// Example event
void onFoo() {
// can be added easily to the map
}
};
Handling this works prefect, but now i want to make BaseClass an abstract base class to derive from like this:
class SpecificClass : public BaseClass {
public:
void onBar() {
// this is gonna be difficult!
}
};
Although i can access the map from SpecificClass i am not able to add onBar because the event_t type is only defined for the BaseClass! Is there any possibility (maybe with templates?) which does not lead to define the event_t for each class i will use...
(It is not neccessary to use templates! Any good/suitable approach would be nice.)
More background information:
This whole thing is for a text based RPG. My base class could be called Location and the specifc one any location e.g. CivicCenter. Each Location object subscribes to my EventSystem which notifies all neccessary objects when i fire an event. Therefore i want to store in a map some pointers to private functions holding the actions with their "name" like onSetOnFire (xD) as the key.
This can't be done with your current map as it stands. Think about what would happen if you could put a child method into the map. Then you could pull a pointer-to-child-member (masquerading as base) out of the map, call it on a base class instance pointer, and then how would it call a derived class on a base class instance which obviously couldn't work.
Would a polymorphic approach work?
Yes; stop using member pointers.
The more correct way of doing what you want is to have an event type and an object pointer. So an event fires on a specific object. The event type would be a non-member function (or a static member). It would be passed the object pointer. And it would call some actual member function of that object.
Nowadays, the event type could be a std/boost::function. However, since the function parameters have to stay the same type for all events, this doesn't really fix your problem. You can't call SpecificClass::onBar from a BaseClass pointer unless you do a cast to a SpecificClass. And the event calling function would not know to do this. So you still can't put SpecificClass::onBar in the std/boost::function object; you still need some standalone function to do the cast for you.
This all just seems to be a terrible use of polymorphism. Why does SpecificClass need to derive from BaseClass at all? Can't they just be two unrelated classes?
You have to use static_cast:
event_t evt = static_cast<event_t>(&SpecificClass::onBar);
This is because it is slightly dangerous to cast to event_t, you could accidently apply it to a BaseClass instance.
How it works (for the skeptical):
class BaseClass {
public:
typedef void (BaseClass::*callback_t)(); // callback method
void doSomething(callback_t callback) {
// some code
this->*callback();
// more code
}
void baseCallback(); // an example callback
};
class DerivedClass : public BaseClass {
public:
void derivedCallback();
void doWhatever() {
// some code
doSomething(&BaseClass::baseCallback);
// more code
doSomething(static_cast<callback_t>(&DerivedClass::derivedCallback));
// et cetera
};
Here is what you should avoid, and why this is potentially dangerous:
void badCodeThatYouShouldNeverWrite()
{
BaseClass x;
// DO NOT DO THIS IT IS BAD
x.doSomething(static_cast<callback_t>(&DerivedClass::derivedCallback));
}
The requirement for a static_cast makes it so you can't "accidentally" pass DerivedClass method pointers in. And if you think this is dangerous, just remember that it's a pointer, and pointers are always dangerous. Of course, there are ways you can do this that involve creating helper classes, but that requires a lot of extra code (possibly making a class for every function you want to pass as a callback). Or you could use closures in C++11, or something from Boost, but I realize that a lot of us do not have that option.
After some thought and a redesign i was able to achieve what i wanted. Although i am stubborn and still using inheritance i have reimplemented the map. This is how it works now:
class Location {
// ...
protected:
std::map<std::string, std::function<void(void)>> m_mEvents;
};
And now i can handle it like this:
class CivicCenter : public Location {
public:
CivicCenter() {
// this is done by a macro which lookes better than this
this->m_mEvents["onTriggerSomething"] =
std::bind(&CivicCenter::onTriggerSomething, this);
}
void onTriggerSomething() {
// ...
}
// ...
};
With easy use of std::bind i am able to implement generic function pointers. When using parameters like in std::function<void(int, int)> remeber to use either boost's _1 and _2 or lambda expressions like me:
std::function<void(int,int)> f = [=](int a, int b) {
this->anotherFunctionWithParams(a, b);
};
But this is just pointed out due to completeness of my solution.
OK, I started using shared-pointers and pass shared-pointers as much as possible. No conversion to raw pointers anymore. This works good, except in this specific case:
Suppose we have a class that also is an observer on another class, like this:
class MyClass : public IObserver
{
public:
MyClass (std::shared_ptr<SomeOtherClass> otherClass);
void DoSomethingImportant();
private:
std::shared_ptr<SomeOtherClass> m_otherClass;
};
This class is used like this in my application:
std::shared_ptr<MyClass> myInstance(new MyClass(otherInstance));
...
myInstance->DoSomethingImportant();
MyClass gets a shared-pointer to another class and stores this in its m_otherClass data member.
In the DoSomethingImportant method, the MyClass instance does lots of important things, including registering itself as an observer on m_otherClass, like this:
m_otherClass->registerObserver(this);
The problem is that the registerObserver method is defined like this:
void registerObserver (std::shared_ptr observer);
It expects a shared pointer, but 'this' is a raw pointer, not a shared one.
I see three ways of solving this:
Find a trick to convert a normal pointer to a shared pointer (see question convert pointer to shared_ptr), but the answers to that question only suggest to copy the shared-pointers, not on how to actually convert the pointer to a shared pointer.
Pass the shared-pointer to ourself to the method, like this: "myInstance->DoSomethingImportant(myInstance);" which seems a bit stupid.
Put the observer part into a separate class. This looks like some overkill, and might make the class harder to understand.
This problem makes it obvious that shared-pointers are just an add-on to C++ (I don't think you have the same problem in other languages/environments like C# (or .Net in general) and Java).
Any other suggestions or tricks on how to handle this situation?
What you need is probably the enable_shared_from_this and shared_from_this facilities. The docs are here
Note that you cannot use shared_from_this until the constructor has fully completed and the object is already owned by another shared_ptr.
struct test : boost::enabled_shared_from_this<test>
{
test() {
// shared_from_this(this); // error, still not owned by another shared_ptr
}
boost::shared_ptr<test> shared() {
return shared_from_this(this);
}
};
int main() {
test * t = new test;
// boost::shared_ptr<test> p = t->shared(); // error, not yet owned by other shared_ptr
boost::shared_ptr<test> owner( t );
boost::shared_ptr<test> p = t->shared(); // [*] ok, "owner" owns the object
}
[*] This part of the example is silly, you could just copy owner into p, instead of calling the method. It is just presented to note when it is ok or not to called shared_from_this inside the test methods.
For observer pattern, the observed object doesn't take the ownership of the observer, why not just using a raw pointer? The life cycle of the observer should be controlled by observer itself.
By using enable_shared_from_this, you introduce cycle dependency for the observer and its observed object. That means if not delete explicitly, the resource will never be released.
How about making the constructor private and having a static construction method like this:
class MyClass : public IObserver
{
public:
static std::shared_ptr<MyClass> createObserver(std::shared_ptr<SomeOtherClass> otherClass);
void DoSomethingImportant();
private:
MyClass (std::shared_ptr<SomeOtherClass> otherClass);
std::shared_ptr<SomeOtherClass> m_otherClass;
};
Then you could instantiate the observer cleanly in the static method and not have to worry about the this pointer at all.
Can you move the registration step into a seperate method? :
shared_ptr<SomeOtherClass> other(new SomeOtherClass());
shared_ptr<MyClass> my(new MyClass());
// register myself to the observer
other->registerObserver(my);
my->DoSomethingImportant();
A good design of observer pattern can be implemented with boost::signal and boost::bind
libraries. I encourage you to have a look.
Best Regards,
Marcin