How to enable copy constructor in Qt
-
Hi
Below is sample code provided,
class Test : public QObject { Q_OBJECT public: Test(QObject *parent = 0){ qDebug()<<Q_FUNC_INFO<<endl; } Test(const Test &obj){ qDebug()<<Q_FUNC_INFO<<endl; } ~Test(){ qDebug()<<Q_FUNC_INFO<<endl; } signals: void testSignal(); }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Test *Tobj = new Test; Test *Tobj2 = new Test(*Tobj); return a.exec(); }
[Added code tags ~kshegunov]
-
@yuvaram This can be compiled and run:
#include <QCoreApplication> #include <QDebug> class Test : public QObject { Q_OBJECT public: Test(QObject *parent = 0){ qDebug()<<Q_FUNC_INFO<<endl; } Test(const Test &obj):QObject(nullptr){ qDebug()<<Q_FUNC_INFO<<endl; } ~Test(){ qDebug()<<Q_FUNC_INFO<<endl; } signals: void testSignal(); }; #include "main.moc" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Test *Tobj = new Test; Test *Tobj2 = new Test(*Tobj); return a.exec(); }
As explained in Qt docs it's a clone, not a copy. Basically it's a new object which copies only the relevant parts of the existing object. Consider also the rule of three/five/zero, http://en.cppreference.com/w/cpp/language/rule_of_three.
Maybe it would be better to not make it like a copy constructor by making a separate init or clone function which takes the existing object. That would avoid possible confusion. Someone with more experience can give an opinion here.
-
Other option: Split the class into a data part (which is not derived of QObject, and fully copyable) and a functionality part. That way, you could do something like this:
Test *Tobj = new Test; Test *Tobj2 = new Test(*Tobj.data());
-
@Eeli-K said in How to enable copy constructor in Qt:
Basically it's a new object which copies only the relevant parts of the existing object.
Which begs the question what are the relevant parts? Are signal-slot connections relevant, is parent-child relationship relevant, or is only the contained data relevant?
As @JohanSolo noted even if you can trick the library to provide a copy constructor, this doesn't necessarily mean you should (actually quite the opposite). In short you should not need to copyQObject
s (or their subclasses), they are not designed to be copied to begin with.Here's the full discussion:
http://doc.qt.io/qt-5.6/object.html#identity-vs-value -
@kshegunov Of course. The writer of a class decides what is relevant for their needs. As can be seen in my example, the QObject is not copied, a default object with no parent is constructed. If one wants to copy some data, it must be done explicitly in the constructor, wheter it's QObject's data or the inherited class data. What I wonder is whether the copy constructor syntax should be used at all if the constructor doesn't really make a copy. It's coding style, but is it bad or good?
-
@Eeli-K said in How to enable copy constructor in Qt:
The writer of a class decides what is relevant for their needs.
He might not know. What do you do with signals and slots? Suppose you have a number of listeners for a signal, do you reconnect them to the new object, do you connect only part of them or not at all? It may depend on a context that's beyond the capabilities for a copy constructor or clone function or w/e to decide.
-
@kshegunov Now I really don't understand. Maybe we are talking about different things. If the writer of a class doesn't know what an object could need he can't write the class. If an object needs to copy some data from another object, it can be copied in one way or another. If the writer has to write (simplified):
MyClass a; //...change a... MyClass b; b.x = a.x; b.y = a.y;
and has to do it often, it can be moved to a function
MyClass b(a);
or
MyClass b; b.init(a);
or
b.clone(a);
or whatever. You can use copy constructor syntax (MyClass(const MyClass&)) for it as I demonstrated; whether you should is another thing. What I asked was about this: should this syntax be left for the real copying only or is it OK to use it for (partly) cloning?
-
@Eeli-K said in How to enable copy constructor in Qt:
If the writer of a class doesn't know what an object could need he can't write the class.
Signals are "special". When you design your class you don't know what will be connected to a signal, so you can't know how the user will connect that signal and what will be attached to it. Even if you accept that all dynamic properties (as Qt allows those) are to be copied, which again is dubious, as you have no information at the time of writing the class what those might represent, you have no information what to do with any signal-slot connections in which the object participates.
Yes, it's possible to copy stuff around, but you will probably never be able to make it work reliably.Same goes for the parent-child relationships. Is the object to be part of the same hierarchy as the one you copy from? If yes, why, if not, why not? This could mean the difference between objects living in one thread and their "copies" living in another and at time of writing of your copy routine or copy constructor, or w/e method you use you don't have the whole picture.
What I asked was about this: should this syntax be left for the real copying only or is it OK to use it for (partly) cloning?
What you could do was suggested by @Asperamanca - split the data that is to be copyable from the
QObject
. Then you know what is what - theQObject
is an identity, but it can aggregate copyable data. So whenever you need you know the data can be copied safely and you leave the user to tinker on "how" and "why" with theQObject
part, he/she already has the usage pattern and the info, you as a class writer don't. -
@kshegunov OK, I think I understand better now. You are talking about the QObject. But I implicitly already accepted that from the beginning. In my example, modified from the original, which is legal C++ there was:
Test(const Test &obj):QObject(nullptr){ qDebug()<<Q_FUNC_INFO<<endl; }
which means the QObject is not copied, right? In the constructor any data can be copied manually if the writer wants so. I haven't suggested that all data should be copied blindly. Only the data which is relevant for the needs, possibly only from the Test class. Then I wondered if it's better to use some other than copy ctor syntax because this will not make a real copy anyways. I didn't answer the original question but wasn't explicit about that, so maybe you thought I was talking about somehow enabling QObject copying?
-
@Eeli-K said in How to enable copy constructor in Qt:
which is legal C++ there was:
[... snip ...]
which means the QObject is not copied, rightYes, it's legal, and yes it's not copied. What I'm trying to argue here is you should not enable the copy constructor to begin with. It's confusing for the user, as your copy constructor doesn't actually copy, and not really productive. Instead, you could just add a constructor that accepts the relevant data as a paremeter, e.g.:
Test(const DataToBeUsed & data, ..., QObject * parent = nullptr) : QObject(parent) { // Do stuff with the data now }
-
@kshegunov said in How to enable copy constructor in Qt:
What I'm trying to argue here is you should not enable the copy constructor to begin with. It's confusing for the user, as your copy constructor doesn't actually copy, and not really productive.
This actually directly answered my question. Don't use the copy ctor syntax if it doesn't make a real copy.