I know that Qobjects are supposed to be identities not values eg you cannot copy them and by default the copy constructor and assignment are disabled as explained in qt documentation. But is it possible to create a new QObject from an existing one using a clone method? Would this be a logic error ?
If I say
QObject b;
QObject a;
b.cloneFrom(a);
or
QObject a = new QOBject();
QObject b = new QOBject();
b->cloneFrom(a);
and the clone method copies stuff like members etc would this be wrong?
And if this is ok can I write my own copy constructor and assignment operator that does just that?
Note: I actually want to try this with classes that inherit qobject.
in my opinion cloning QObjects is almost always semantically broken and leads to unwanted side-effects, due to them having an "identity" as you already said. Therefore, cloning breaks all the assumptions one has about QObjects, like their signal/slot connections and dynamic properties. You should consider if the objects to clone really need to be QObjects, or if the "value-part" you want to have cloned could be factored out.
And if at all, cloning makes only sense for your specific subclasses of QObjects, not for QObjects themselves (which have no real "value-like" properties).
also, A; B; A.cloneFrom( B ) looks broken, as it doesn't work if B is instance of a subclass of B instead of B itself.
Clone should be done via a virtual B* B::clone() const I'd say.
I think that the best practice in this case to create class with the data you want to copy between QObjects. This class should not be derived from QObject or any class derived from QObject. And this class will be "value container". In this case you should be able to solve your problem in really good way.
One more tip: for this class you can use implicit data sharing with copy on write to reduce overhead of unnecessary copying: http://doc.qt.io/qt-5/implicit-sharing.html
Related
This question already has answers here:
Do I have to delete it? [Qt]
(3 answers)
Closed 4 years ago.
When looking at Qt examples (on Qt documentation like movieplayer example, or here), I never see the member destructors explicitly called.
A class definition is like:
class foo : public QParent {
Q_OBJECT
QStuff stuff;
foo (QWidget *parent) : QParent(parent)
{
stuff = new QStuff(this);
}
};
My problem is that I never see something like delete stuff;
So my questions are:
Are QObject derived class instances which parent is not NULL automatically deleted when their parent is?
Is it dangerous to delete a QObject derived member without setting it to NULL?
I guess the answers are Yes and No, but I'm not sure.
For the first question yes. You can check the Qt docs here
where it is stated clearly:
QObjects organize themselves in object trees. When you create a
QObject with another object as parent, the object will automatically
add itself to the parent's children() list. The parent takes ownership
of the object; i.e., it will automatically delete its children in its
destructor. You can look for an object by name and optionally type
using findChild() or findChildren().
For the second question, the answer deserves a little bit more of explanation. If you have QObject pointers members that are not children of your object, you have to handle their disposal manually in the destructor of your class.
You can in theory use delete on any QObject* to invoke its destructor, but since Qt objects have a powerfull event system based on signals/slots, you must be aware of the interactions with event loops. If you brutally delete a QObject connected to another QObject while the latter one is still processing a signal coming from the first one, you may end up with some problems.
This holds in both mono and multi-threaded applications. You should therefore avoid the use of delete in favor of QObject::deleteLater() that will defer the deletion of the QObject until all the signal/slots related to it have been processed.
Lastly, in the context of the implementation of a destructor it doesn't really matter if you set the pointer to null, because it will be unavailable for further use anyway. It may be important if you delete the pointee in some other method, while your instance is still alive, and you set the pointer to null to flag it as uninitialized.
No, you do not need to delete member objects. They will get destroyed automatically when the parent class object gets destroyed.
See this FAQ.
In the case of Qt QObject pointer members, then the parent is the owner and is responsible for deleting the QObject. See here.
My goal is this:
QWidget *p = new QSpinBox(0); // This can be any type of QWidget.
QWidget* Get()
{
/*
Here using p, I need to return a NEW object of QSpinBox or whatever
the qwidget assigned to p. I can't return p because it will be deleted
after this method, so the next time p would be empty.
*/
}
It's used for the QStyledItemDelegates::createEditor() method. The widget returned from get will be deleted when the delegate editing is done.
All QObjects are not copyable by definition. See its header file.
Same applies to QSpinBox.
Reason is simple cloning of signal slots memory management could lead to unpredictable results, so it was disabled by design.
The copy of a pointer to an object doesn't copy the object in any way. In Qt the copy of QObject derived classes is indeed disabled, but you can copy pointers to the object around as much as you want, or until you run out of memory...
Due to the design of Qt QObject derived classes have unique identities. This means they must not be copied, at least in the rational sense of the term. You could however write your own "clone function" that creates a new instance with unique identity and applies all of the properties of the object p points to to the new instance. E.g. you can fake it to a certain amount but don't expect to get a copy functionally identical to the original. If you want to get a fully functionally identical clone, you will have to implement your own signal and slot mechanism instead of using the one provided by Qt.
You CAN indeed return p - but it will point to nothing if you call delete on it. Keep in mind returning p will simply copy the pointer, it has nothing to do with the actual object pointed to. p is just a number.
Edit:
At a deeper look at the "reflection facilities" provided by Qt, it looks like you could get signals and slots to clone, but it is not pretty - you have to query every QMetaMethod of the QMetaObject associated with the particular instance to find the signals, but then you hit a brick wall - you will have to resort to using private APIs (a big no-no in 99.9999% of the cases) in order to query for the signal receivers in order to connect the new copy to them as well. Definitely not something that was intended to be done. In short, you need to rethink your strategy at getting the problem solved.
Overall, as I mentioned in the comments, your problem seems to be bad design, and even though it is technically possible to make the bad design work, you'd be much better if you simply improve your design and avoid arduous if not even masochistic endeavors.
s is a pointer, which can be copied and modified at will; modifications to the copy will never affect the original. If what you meant was in fact the object which s referred to, then it's sufficient to provide it with a copy constructor and a copy assignment operator; depending on the content of the class, the compiler may have generated these for you.
Depending on the content, it's also possible that the compiler generated versions don't do what you need.
Given the name of the class, I suspect that it is part of Qt. In that case, check the documentation. It may support cloning, in which case, what you probably want is a clone.
I am creating a mixin between two classes using the boost::enable_shared_from_this template. So I am adding a new functionality to this class:
class MyOldClass :
public Connection,
public boost::enable_shared_from_this<MyOldClass>
{ ... };
I did use this before with a normal class (not a QtObject, just a C++ plain class) and everything works.
But now I am doing the same with a QMainWindow and it basically crash:
class MainWindow :
public QMainWindow,
public Connection,
public boost::enable_shared_from_this<MainWindow>
{ Q_OBJECT ... };
Is it possible that there is any problem doing this with a QObject? Not sure why this is happening.
Thank you.
You mentioned in the comments that you don't create a shared_ptr before you call shared_from_this(). But that's the problem. x.shared_from_this() only works once a shared_ptr to x exists. If you never create one, you're violating a precondition of shared_from_this(), so your program has undefined behaviour.
shared_from_this() only serves to retrieve a pointer sharing ownership with existing shared pointers; it cannot be used to create the first one.
Ok folks, it has been my fault but the answer could help to someone:
As Angew said it is necessary to create the first instance of MainWindow using a shared_ptr (I didn't understand your question the first time).
I was doing this but I was using the std::shared_ptr implementation instead of the boost::shared_ptr one. Mixing both was producing this results.
It works now but as Angew said one has to be very careful using shared_ptr's with the Qt ownership scheme.
The inheritance order specified in the MainWindow declaration is the only one valid. As Angew said: "When inheriting from QObject or a class derived from it, QObject (or that derived class) must be the first one in the base class list. So that won't work"
Thank you
I would like to make sure no one is able to delete any objects from my class hierarchy other then by using a provided Destroy method.
The rationale is that any object from this hierarchy needs to take a special write mutex before it starts to destroy itself to make sure objects are not deleted while another thread is using them.
I know I could prevent this problem with reference counting but it would be a much bigger change to the system also in terms of potential performance impact and memory allocation.
Is there a way to somehow efficiently/smartly make all the destructors protected so that child classes can call their parents destructors while outsiders have to use Destroy?
One solution that is safe (ie. it will not rot) that I came up with is to make all the destructors private and declare each derived class as a friend of the base class but I'd prefer something more elegant, less manual and easier to maintain (like not requiring to modify base classes in order to derive from them).
Is there anything like this available? Maybe some smart trick that makes things "work" as I'd like?
ps. The solution I chose for now is to NOT prevent anyone from calling delete in all cases (just made it protected in the base class) but detect this situation and call abort in the base class destructor.
Don't try to reinvent the lifetime mechanisms provided by the language.
For an object of your class to be correctly initialised it needs to also be able to clean itself up.
In its constructor pass either the mutex, or a means of obtaining a mutex, which it can use in its destructor.
Thanks for all your feedback and discussion. Yes - it proved it's impossible to do what would be my natural first choice :( (to have the "protection" of the destructor take effect in derived classes just as it's "virtuality" does).
My solution in this particular case (solving all potential problems with being able to make hones mistakes by introducing new derived classes that violate previous agreements AND keeping the solution in one place/maintainable (no code duplication in derived classes etc)) is:
Make all the existing class hierarchy destructors I can find protected
Provide a Destroy method in the base class that can be used to initiate the destruction of these objects - if called the method lights up a flag on the destructed object that it was properly destroyed and then calls delete on it
In the base class destructor (once we get to it) check the flag - if it's not set it means someone introduced a new class and called delete on it directly or avoided the compilers protection checks in some other way (abused some friendships etc) - I abort the application in this case to make sure the issue cannot be ignored/missed
I had the same needs, but for a different reason. In our company framework, nearly all classes derive from a common BaseObject class. This object uses a reference count to determine its life time. BaseObject has in particular these three methods: retain(), release() and autorelease(), heavily inspired from Objective-C language. The operator delete is only called inside release() when the retain count reaches 0. Nobody is supposed to call delete directly, and it is also undesirable to have BaseObject instances on stack.
Therefore, all our destructors should be protected or private. To enforce this, as I know it is impossible from the language, I wrote a Perl script that looks for all destructors within a source directory and makes a report. It is then relatively easy to check that the rule is respected.
I made the script public, available here: https://gist.github.com/prapin/308a7f333d6836780fd5
It can be done with help of testing. For a class with an protected destructor you need 2 test cases:
one function (in one file) which fails to compile simply creating such an object
one function (in second file) which creates an object with an derived class which compiles.
If both test cases work I think you can be sure your classes are protected as you like.
I don't know wether you are able to implement it with your build system but I have an example using bjam (from boost) at git hub. The code is simple and works for gcc and msvc. If you don't know bjam you should look inte Jamroot.jam. I think it is clear without any further comment how this simple example works.
This question is fairly fundamental.I gave a simple and straighfoward test on my cygwin:
class Example {
public:
Example(){ cout<<"dude..."<<endl; }
~Example(){ cout<<"see ya"<<endl; }
public:
static Example *GetInstance(){
if(m_instance==NULL){
m_instance = new Example();
cout<<"watch out bro"<<endl;
}
return m_instance;
}
public:
void exp(){cout<<"greetings"<<endl;}
private:
static Example *m_instance;
};
int main(){
Example a;
return 0;
}
Obviously,the output is:
dude...
greetings
see ya
Technically singleton and typical constructor are pretty much different stories in c++ programming since singleton puts constructor as private while typical way is opposite.In my recent internship experiences I have noticed that most coders implement APIs in this manner.
I just wonder if that is the case or unnecessary when both class construction approaches exist in parallel.
UPDATE
Is constructor & singleton existing in one program practically nonsense cuz singleton stuff in this scope would become useless codes like unhazardous trash?
SUMMARY
This is quite a nonsense question...
and what's more,thanks to all of you brilliants
constructor and singleton design pattern are "mutually exclusive" and in terms of vulnerbility,it is the same story as global variables kill our debug time...
By making the constructor of Example public, you allow users of your class to create an instance directly. If your design requires only one instance of your singleton then this allows users to inadvertently subvert this requirement. If you had made the constructor private then calling GetInstance() would be the only way to create an Example object, thus enforcing the requirement to allow only one instance to be created.
Note that static objects are destroyed in reverse order to which they were created. This causes a problem if the objects refer to each other. This is a trap for people maintaining your code, and if you have more than a few such objects this quickly becomes unmanageable.
Many developers consider singletons to be a Bad Thing much like global variables:
https://sites.google.com/site/steveyegge2/singleton-considered-stupid
When using the Singleton design pattern you always should make the constructors (copy constructor as well) and the operator = as private to ensure there will be only one instance of the given class. Otherwise the Singleton pattern wouldn't make much sense.
I think that you missed the whole concept of singleton. Singleton means that there is only one instance, but public constructor can construct lot of objects.
I think that example is broken. It allows user to create multiple "singletons" and then obviously they are no singletons.
In singleton constructor has to be private.
Just making the constructor private doesn't make the class Singleton. For that you have to make sure no other instances are present in the memory before you call the constructor. Even though the constructor is private any number of instances of the class can be created from static class members
Singleton is a technique to make sure there's only one instance to a class created. By exposing a public constructor you're obviously opening the door for multiple instances thus your class may not be called a singleton.
However it still has a static GetInstance() method that's somewhat expected as a singleton interface, and that makes it confusing to who didn't write the code (or even to the author some time later).