为啥编译器在尝试使用 C++11 样式初始化对象数组时隐式删除​​构造函数

Posted

技术标签:

【中文标题】为啥编译器在尝试使用 C++11 样式初始化对象数组时隐式删除​​构造函数【英文标题】:Why compiler implicitly deletes constructor while trying to initialize an array of objects with C++11 style为什么编译器在尝试使用 C++11 样式初始化对象数组时隐式删除​​构造函数 【发布时间】:2019-06-28 16:00:42 【问题描述】:

我正在尝试编写一个非常简单的构造函数 init 列表,但在对象数组上存在不足。编译器说:

parentclass.cpp:5: error: use of deleted function ‘SubClass::SubClass(SubClass&&)’
     , subObjectsthis
                      ^

我确信这是有关现代 C++ 的基本概念,并且看到了许多已回答的问题。但他们都没有澄清我错过了什么。

这是产生此编译器错误的基本代码(g++ 8.3.0)

QtCreator 项目文件:

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

ma​​in.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)


创建动态数组可能是一种解决方法,但我正在尝试适应现代 C++。由于我主要是嵌入式人,所以动态数组也很多时候没有问题。

提前致谢。

编辑说明: 我已经更新了一个最小可重现示例的问题。

另外,如果我对 SubClass 的构造函数使用 'explicit' 关键字,这次它会给出如下错误:

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

'explicit' 关键字防止删除构造函数,但这次编译器不接受指针类型,即使它们都派生自同一个类。

下一个编辑说明: 用双括号更改了 subObjects 初始化列表。

【问题讨论】:

Can't reproduce 不使用Q_OBJECT 宏时是否也会出现同样的错误?当不是从QObject 派生时?很高兴确认这是一个 QT 问题。 (另外,知道这两个方面中的哪一个会触发编译器错误,可以明确地指示查看的位置。) 你试过subObjects this ,没有额外的大括号吗?我的猜测是,subObjects this 被解释为subObjects SubClassthis ——创建一个临时对象,然后尝试将其复制或移动到数组元素中;但 QObject 不可复制也不可移动。 这个例子非常远非最小。尝试提出一个单一的源文件,没有框架依赖。 subObjects 是一个 SubObject 类型的数组。您正在尝试使用 pointer 将其 ibitialise 指向 unrelatedParentObject 的对象。你的意图是什么? 【参考方案1】:

我在link 中找到了解释,我已经怀疑了。

这是 Qt 开发人员的设计选择。他们出于各种原因使 QObject 类不可复制,包括不搞乱 SIGNALS/SLOTS 机制。

作为一种解决方法,我将 subObjects 定义为 SubClass* 指针数组,然后在 ParentClass 的构造函数中使用 new 关键字创建 3 个实例。

P.S.: Oktalist,这就是您的代码没有产生错误的原因。 QObject 必须像在 Qt 框架中一样完全定义。

【讨论】:

以上是关于为啥编译器在尝试使用 C++11 样式初始化对象数组时隐式删除​​构造函数的主要内容,如果未能解决你的问题,请参考以下文章

为啥就地成员初始化在 C++11 中使用复制构造函数?

我应该使用啥标志来强制执行良好的 C++11 样式?

为啥在直接初始化和赋值中传递 lambda 而不是复制初始化时会编译?

为啥在尝试调用采用动态参数的基本构造函数/方法时会出现此编译错误?

VS2010 编写c语言变量为啥要初始化?

Visual Studio C++11g 编译错误 - 初始化程序太多