How to enable copy constructor in Qt
-
wrote on 14 Jun 2017, 04:17 last edited by
How to enable copy constructor in Qt.
-
wrote on 14 Jun 2017, 04:21 last edited by
Hi yuvaram ,
Your question is very general. It might be a good idea to show us the relevant code of your class.
-
wrote on 14 Jun 2017, 06:27 last edited by kshegunov
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]
-
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]
wrote on 14 Jun 2017, 06:49 last edited by@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.
-
wrote on 14 Jun 2017, 09:46 last edited by
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());
-
@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.
@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 -
@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-valuewrote on 14 Jun 2017, 10:50 last edited by@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?
-
@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.
-
@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.
wrote on 14 Jun 2017, 21:29 last edited by@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?
-
@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. -
@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.wrote on 15 Jun 2017, 21:31 last edited by@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?
-
@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 }
-
@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 }
wrote on 15 Jun 2017, 21:47 last edited by@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.
1/14