Create a default inline constructor in a custom QT object

I am reading this QT doc page about user types and it states the following:

The default constructor, copy constructor, and destructor are required and must be publicly accessible if this type is to be integrated into the meta-object system.

Suppose I have an object that needs to be built with some required parameters, because it does not make sense to build using the default constructor, for example:

struct IntPair { IntPair(int first, int second); ~IntPair(); }; 

To make it available in the QT metadata system, as indicated in the document, a default constructor is required. But it makes little sense to give the opportunity to build an IntPair object without a pair of integers (sorry for the ugly example).

Is there any way to achieve this without implementing the default constructor? I am thinking of some kind of friendship between my object and the QT meta-object system ...

Basically, I cannot understand why a default constructor is needed.

+7
source share
4 answers

This is due to the implementation of QVariant (templated).

Take a look at qvariant.h in the QT5.5 source tree and you will find the following:

  T t; if (v.convert(vid, &t)) return t; return T(); 

And:

  old->~T(); new (old) T(t); //call the copy constructor 

Therefore, it is necessary to create a public constructor / descriptor and copy constructor.


The advantage of all this is that you can use your own type in signals / slots (and in other meta objects), but there are disadvantages, as in your situation. This is just a compromise that you need to live with.

As a workaround, you can have some kind of init () method that actually initializes the object after it is created. Not so safe / elegant, but it works.

+2
source

In this regard, there is a design . This is due to the discussion of "Identity vs Value," which seems to me to be too long to insert here.

As for how @AlexanderVX commented on the use of default values ​​in arguments.

+1
source

A custom data type must have standard default constructors, because many parts of the Qt structure will call it to avoid returning null pointers. For instance. QVariant and containers (e.g. QHash :: value ()).

In your case, IntPair (): IntPair (0,0) {} should be nice, shouldn't it?

In many cases, it is convenient to store data in objects that mimic the implicit Qt exchange pattern (see http://doc.qt.io/qt-5/implicit-sharing.html ), in which case the default constructor can easily be initialized with using QSharedDataPointer (0), and each accessory returns the default value when the pointer is null (for example, 0 for int, QString () for QString, etc.), guess that: each accessory can provide a default value by calling the standard default constructor for the data type, because it must have one :-).

0
source

The question has two parts:

  1. Reaching a custom meta object without a default ctor implementation.
  2. Understanding why Qt defaults to Qt in this case.

Other respondents have already applied (2).

I want to contact (1).

I wrote a class, and I intend for users of this class to call ctor, which I wrote, which requires several arguments. However, due to requirements related to Qt, I have to add a constructor with a null argument.

This would make me happy to at least make the ctor with a null argument private, so that I could force the use of this ctor to be forbidden to all user code, EXCEPT the moc generated β€œmagic” code.

Hello, happiness! It is possible.

You can really use friendships to make ctor private by default and still use Qt Metatype.

It looks something like this:

 class MyClass { Q_GADGET Q_PROPERTY(QString text READ text) public: MyClass(QString text, bool sometruth, int someint); QString text() const { return text_; } private: // Works in my project using Qt 5.12. (see hints below if it fails for you) friend struct QtMetaTypePrivate::QMetaTypeFunctionHelper<MyClass, true>; // Prefer the ctor that takes arguments. This ctor only exists to satisfy Qt. MyClass(); QString text_; }; 

There are two ways to solve the problem of figuring out what to make friends.

You can mark ctor as private, try to recompile and parse the compiler error to find out what other type is trying to access the ctor of your class.

Or you can put assert(false); in the body of your ctor, create a binary file with debugging symbols (including Qt debugging symbols), and then look at the stack in the debugger when the statement fails. The stack will show the internal member function of Qt or the free function that called in your ctor. Friend, whatever this subscriber is.

This last method (using a debugger) works for me. (I was not fluent enough in the compiler to determine what type of output of the giant compiler error was what I needed to add as my friend.)

0
source

All Articles