Why compiler implicitly deletes constructor while trying to initialize an array of objects with C++11 style

Viewed 125

I'm trying to write a very simple constructor init list but falling short on an array of objects. The compiler says:

parentclass.cpp:5: error: use of deleted function ‘SubClass::SubClass(SubClass&&)’
     , subObjects{this}
                      ^

I'm sure this is a basic concept about Modern C++ and seen many answered questions around. But none of them clarified what I'm missing.

Here's the basic code which creates this compiler error (which is g++ 8.3.0)

QtCreator Project File:

QT -= gui

CONFIG += c++11 console
CONFIG -= app_bundle

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp \
        parentclass.cpp \
        subclass.cpp

HEADERS += \
    parentclass.h \
    subclass.h

main.cpp:

#include <QCoreApplication>
#include "parentclass.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    ParentClass pClass;

    return a.exec();
}

parentclass.h:

#ifndef PARENTCLASS_H
#define PARENTCLASS_H

#include <QObject>
#include "subclass.h"

class ParentClass : public QObject
{
    Q_OBJECT
public:
    explicit ParentClass(QObject *parent = nullptr);

private:
    SubClass subObjects[3];
};

#endif // PARENTCLASS_H

parentclass.cpp:

#include "parentclass.h"

ParentClass::ParentClass(QObject *parent)
    : QObject(parent)
    , subObjects{ {this} }
{
}

subclass.h:

#ifndef SUBCLASS_H
#define SUBCLASS_H

#include <QObject>

class SubClass : public QObject
{
    Q_OBJECT
public:
    SubClass(QObject *parent = nullptr);
};

#endif // SUBCLASS_H

subclass.cpp

#include "subclass.h"

SubClass::SubClass(QObject *parent) 
  : QObject(parent)
{
}

Creating a dynamic array could be a workaround but I'm trying to adapt to Modern C++. Since I'm mostly an embedded guy, dynamic arrays are also out of question many times.

Thanks in advance.

Edit Note: I've updated the question for a minimum reproducible example.

Also if I use 'explicit' keyword for the constructor of SubClass, this time it gives an error like this:

parentclass.cpp:5: error: could not convert ‘(ParentClass*)this’ from ‘ParentClass*’ to ‘SubClass’
     , subObjects{this}
                      ^

'explicit' keyword prevents deletion of the constructor but this time compiler does not accept pointer type, even if they are both derived from the same class.

Next Edit Note: Changed subObjects init list with double braces.

1 Answers

I've found the explanation in this link, which I was suspecting already.

This is a design choice by the developers of Qt. They made QObject class non-copyable for various reasons, including not messing up with the SIGNALS/SLOTS mechanism.

For a workaround, I'll define the subObjects as an array of SubClass* pointers, then create 3 instances with new keyword in the constructor of ParentClass.

P.S.: Oktalist, this is why your code is not producing the error. QObject has to be completely defined as in the Qt framework.

Related