Qt继承和类构造函数混淆 我对QT C++有点陌生,我想我有一个小东西,但不能弄清楚是什么。 我试图做一个简单的QtC++应用程序,只是为了熟悉它,但是我面临一些问题,首先,我有Voor类,它是主要的应用程序类,另一个被称为记录器的类,它将被用于主Voor类。为了简单起见,我省略了不相关的部分, 以下是文件:

Qt继承和类构造函数混淆 我对QT C++有点陌生,我想我有一个小东西,但不能弄清楚是什么。 我试图做一个简单的QtC++应用程序,只是为了熟悉它,但是我面临一些问题,首先,我有Voor类,它是主要的应用程序类,另一个被称为记录器的类,它将被用于主Voor类。为了简单起见,我省略了不相关的部分, 以下是文件:,c++,qt,class,inheritance,class-constructors,C++,Qt,Class,Inheritance,Class Constructors,沃托 #pragma一次 #包括 #包括“ui_votor.h” #ifndef TSTRECORD\u H #定义TSTRECORD_H #恩迪夫 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括“recorder.h” 类VOTor:公共QMainWindow { Q_对象 公众: VOTor(QWidget*parent=Q_NULLPTR); 记录器xs; 私人: Ui::VOTorClass Ui; }; votor.cpp #包括“votor.h” VOTor::VO

沃托

#pragma一次
#包括
#包括“ui_votor.h”
#ifndef TSTRECORD\u H
#定义TSTRECORD_H
#恩迪夫
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“recorder.h”
类VOTor:公共QMainWindow
{
Q_对象
公众:
VOTor(QWidget*parent=Q_NULLPTR);
记录器xs;
私人:
Ui::VOTorClass Ui;
};
votor.cpp

#包括“votor.h”
VOTor::VOTor(QWidget*parent):QMainWindow(parent),xs(parent)
{
ui.setupUi(这个);
//xs=记录器();
}
录音机

#pragma一次
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类记录器:公共QObject
{
Q_对象
公众:
//记录器();
记录器(QObject*父对象);
~recorder();
//省略了一些与录制相关的功能,以获得更多关注
私人:
//为了简单起见,省略了一些成员,只是一些与问题无关的整数、字符和qt对象
记录器.cpp

#包括“recorder.h”
记录器::记录器(QObject*父级):QObject(父级)
{
//只是正常初始化省略的成员
}
//记录器::记录器(){}
录音机::~recorder()
{
}
正如您所看到的,recorder对象是votor类中的一个成员。现在,我需要调用recorder构造函数来初始化它的父级。现在,我知道我不能只做(在votor.h内部)

所以, 1-除了初始化列表之外,我是否可以调用记录器构造函数? 我想要另一种方式,因为我使用recorder xs(..)比使用initialization list更方便,我觉得(只是觉得)使用initialization list很麻烦(不是性能方面的问题,而是可读性方面的问题)。我也知道我可以使用动态分配,但我不想在没有充分理由的情况下使用它

2-我决定使用初始化列表调用记录器构造函数并将(Qobject*parent)传递给记录器。代码已成功生成,但在运行时,它会出现访问冲突错误,我无法解释原因。。。 它给出: “访问冲突读取位置0x7C32F08D。”

我想我错过了一件小事。我希望知道是什么错了

编辑: 正如@p-a-o-l-o所建议的,访问冲突来自省略的代码,因此,我在这里发布它,因为我不知道我的代码中存在什么问题:

recoder.h的完整版本

类记录器:公共QObject
{
Q_对象
公众:
记录器();
//记录器(QObject*父对象);
~recorder();
无效记录();
无效停止();
公众时段:
void stateChanged(QAudio::State);
私人:
无符号字符状态;
QBuffer*语音缓冲区;
QAudioFormat*格式;
QAudioDeviceInfo*信息;
QAudioInput*音频输入;
无符号字符writeWav(QByteArray*);
};
该部分根据调试模式(recorder类的构造函数)导致访问冲突

recorder::recorder():QObject(Q_NULLPTR)
{
状态=0;
voiceBuffer->open(QIODevice::WriteOnly);
格式->设置采样率(8000);
格式->设置通道计数(1);
格式->设置采样(16);
格式->setByteOrder(QAudioFormat::LittleEndian);
格式->设置编解码器(“音频/pcm”);
格式->设置采样类型(QAudioFormat::SignedInt);
*info=QAudioDeviceInfo::defaultInputDevice();
音频输入=&QAudioInput(*信息,*格式);
//audioIn->stateChanged.connect(stateChanged);
//连接(audioIn,&QAudioInput::stateChanged,stateChanged);
连接(音频输入,信号(stateChanged(QAudio::State)),此,插槽(stateChanged(QAudio::State));
}
关于问题#1:正如在评论中正确建议的那样,
QObject
派生类的正确构造函数将具有
nullptr
默认参数:

recorder(QObject *parent = Q_NULLPTR);
如果您确实需要该
父对象来初始化构造中的其他成员,那么您别无选择,必须以某种方式调用该构造函数

否则,请使用无参数构造函数并初始化其中的其他成员:

recorder::recorder() : QObject(Q_NULLPTR)
{
    //just initializing the omitted members normally
}
这样的构造函数将被自动调用,这里不需要初始化列表

如果仍然需要
记录器
对象的父对象,请在
VOTor
构造函数中为其提供一个父对象:

VOTor::VOTor(QWidget *parent) : QMainWindow(parent)
{
    ui.setupUi(this);
    xs.setParent(parent);
}
关于问题#2:从您发布的代码中我可以看到,访问冲突与Qt亲职无关,必须与
记录器中的(省略的)代码相关

只想澄清一下:为成员对象设置父对象总是安全的,因为在调用
~QObject()
之前,它将超出范围,因此在
~QObject()
可能对其调用delete之前,它将从子对象列表中删除

以OP代码为例,析构函数的顺序如下:

~VOTor()
~recorder() ---> xs is removed from the children list
.
.
.
~QObject() ---> will call delete on all children, but ws is not in the list anymore
非常清楚父项和子项的构造/销毁顺序:简言之,如果在堆栈上创建子项,则在父项之后创建子项之前,一切都将正常。
但是,同样,如果孩子恰好是父类的成员,出于上述原因,也可以(即使其构造实际上发生在其父类之前).

如果类型没有默认构造函数,则必须使用初始化列表。如果类型声明为常量,则使用相同的初始化列表。这样,编译器可以确保正确构造对象。对于访问冲突,应使用调试器找出代码的错误所在。通常,调试器会停止
~VOTor()
~recorder() ---> xs is removed from the children list
.
.
.
~QObject() ---> will call delete on all children, but ws is not in the list anymore