为啥编译器在尝试使用 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
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)
创建动态数组可能是一种解决方法,但我正在尝试适应现代 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 指向 unrelated 类 ParentObject
的对象。你的意图是什么?
【参考方案1】:
我在link 中找到了解释,我已经怀疑了。
这是 Qt 开发人员的设计选择。他们出于各种原因使 QObject 类不可复制,包括不搞乱 SIGNALS/SLOTS 机制。
作为一种解决方法,我将 subObjects 定义为 SubClass* 指针数组,然后在 ParentClass 的构造函数中使用 new 关键字创建 3 个实例。
P.S.: Oktalist,这就是您的代码没有产生错误的原因。 QObject 必须像在 Qt 框架中一样完全定义。
【讨论】:
以上是关于为啥编译器在尝试使用 C++11 样式初始化对象数组时隐式删除构造函数的主要内容,如果未能解决你的问题,请参考以下文章
为啥在直接初始化和赋值中传递 lambda 而不是复制初始化时会编译?