【发布时间】:2020-01-12 16:36:37
【问题描述】:
我对 Qt C++ 有点陌生,我认为我缺少一个小东西,但不知道是什么。
我正在尝试制作一个简单的 Qt C++ 应用程序只是为了熟悉它,但我遇到了一些问题,首先,我有一个 votor 类,它是主要的应用程序类,还有一个叫做 recorder 的类,它将在主要投票者类中使用。为简单起见,我省略了不相关的部分, 以下是文件:
投票者.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_votor.h"
#ifndef TSTRECORD_H
#define TSTRECORD_H
#endif
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>
#include "recorder.h"
class VOTor : public QMainWindow
{
Q_OBJECT
public:
VOTor(QWidget *parent = Q_NULLPTR);
recorder xs;
private:
Ui::VOTorClass ui;
};
投票者.cpp
#include "votor.h"
VOTor::VOTor(QWidget *parent) : QMainWindow(parent), xs(parent)
{
ui.setupUi(this);
//xs = recorder();
}
recorder.h
#pragma once
#include <QDebug>
#include <QObject>
#include <QtCore/qbuffer.h>
#include <QtCore/qiodevice.h>
#include<QtMultimedia/qaudioformat.h>
#include<QtMultimedia/qaudiodeviceinfo.h>
#include<QtMultimedia/qaudioinput.h>
class recorder : public QObject
{
Q_OBJECT
public:
// recorder();
recorder(QObject *parent);
~recorder();
//Some functions related to recording omitted for more focus
private:
//omitted members for simplicity, just some integers, chars and qt objects not related to problem
recorder.cpp
#include "recorder.h"
recorder::recorder(QObject *parent) : QObject(parent)
{
//just initializing the omitted members normally
}
//recorder::recorder() {}
recorder::~recorder()
{
}
如您所见,recorder 对象是 votor 类中的成员。现在,我需要调用记录器构造函数来初始化其父级。现在,我知道我不能只做(在 votor.h 中)
recorder xs(parent);
所以, 1-除了初始化列表之外,还有其他方法可以调用记录器构造函数吗? 我想要另一种方式,因为我使用记录器 xs(..) 比使用初始化列表更方便,我觉得(只是觉得)使用初始化列表很重(不是性能方面,而是可读性)。我也知道我可以使用动态分配,但我不想在没有充分理由的情况下使用它。
2- 我决定使用初始化列表来调用记录器构造函数并将 (Qobject* parent) 传递给记录器。代码构建成功,但是在运行时,它给出了访问冲突错误,我不知道为什么...... 它给: "访问冲突读取位置 0x7C32F08D。"
我想我错过了一些小事。我希望知道什么是错的。
编辑: 正如@p-a-o-l-o 所建议的,访问冲突来自省略的代码,所以,我将其发布在这里,因为我不知道我的代码有什么问题:
recoder.h 完整版
class recorder : public QObject
{
Q_OBJECT
public:
recorder();
//recorder(QObject *parent);
~recorder();
void record();
void stop();
public slots:
void stateChanged(QAudio::State);
private:
unsigned char state;
QBuffer* voiceBuffer;
QAudioFormat* format;
QAudioDeviceInfo* info;
QAudioInput* audioIn;
unsigned char writeWav(QByteArray*);
};
根据调试模式导致访问冲突的部分是记录器类的构造函数
recorder::recorder() : QObject(Q_NULLPTR)
{
state = 0;
voiceBuffer->open(QIODevice::WriteOnly);
format->setSampleRate(8000);
format->setChannelCount(1);
format->setSampleRate(16);
format->setByteOrder(QAudioFormat::LittleEndian);
format->setCodec("audio/pcm");
format->setSampleType(QAudioFormat::SignedInt);
*info = QAudioDeviceInfo::defaultInputDevice();
audioIn = &QAudioInput(*info, *format);
//audioIn->stateChanged.connect(stateChanged);
//connect(audioIn, &QAudioInput::stateChanged, stateChanged);
connect(audioIn, SIGNAL(stateChanged (QAudio::State) ), this, SLOT(stateChanged(QAudio::State)));
}
【问题讨论】:
-
如果一个类型没有默认构造函数,那么你必须使用初始化列表。如果类型声明为常量,则相同。这样,编译器可以确保正确构造对象。
-
对于访问冲突,你应该使用调试器来找出你的代码做错了什么。通常调试器会在错误发生时停止,通过查看代码和变量,它有助于确定问题。无论如何,如果没有重现访问冲突的代码,将很难提供帮助。
-
程序在组装时停止,我不知道是什么原因。我唯一确定的是问题来自初始化列表中的父级,因为当我更改代码并使用默认构造函数进行记录时,然后使初始化列表不带参数,它运行良好。
-
当您尝试在堆栈上分配 QObject 时,您可能需要使用初始化列表,就像您在此处所做的那样。但是,在 Qt 中,有必要通过将子对象放在指针中来在堆上分配子对象,除非所有东西都将在程序结束时被销毁。转到 Qt 帮助屏幕,查找 ~QObject 并阅读第一个警告。如果你在堆上分配那么你将有更多的初始化选项
-
@MohammadAKanan 我进一步编辑了答案,但我想你已经猜对了
标签: c++ qt class inheritance class-constructors