关于QT的一个问题(为什么创建对象都用new)

文章讨论了Qt编程中,为何推荐在堆上创建子控件,如QPushButton,而非栈对象。原因在于栈对象生命周期短,易在构造函数结束后被析构,导致无法正常显示。使用`new`操作符创建对象在堆上存储,确保其在整个程序运行期间可用。

先说结论:Qt子控件最好在堆上创建,栈对象容易被自动析构导致错误。栈对象生命周期太短,改为堆对象后可正常显示。

解释:以下文为例:
在这里插入图片描述
我用下面这两代码创建出来的button,在窗口中显示不出来
一定要用new的形式才行

    QPushButton qbutton;
    qbutton.setParent(this); //设置按钮的父对象为窗口,这样按钮就在窗口显示

在这里插入图片描述

用new就可以在窗口中显示出来了

    QPushButton *qbutton = new QPushButton();
    qbutton->setParent(this); //设置按钮的父对象为窗口,这样按钮就在窗口显示

在这里插入图片描述
我自己想了一下,跟变量的生存周期有关,PushButton这个控件是在构造函数中创建的,相当于是局部变量,构造完就被释放了,但其实还需要在main()函数中调用show()把窗口显示出来,而此时PushButton已经被释放了。而以new的形式创建的,是在堆上开辟空间,直到整个程序运行结束才会被释放。

QT DLL库中创建对话框对象崩溃,可能有以下几种原因: ### 资源加载问题 在DLL中使用Qt资源时,若资源未正确加载,可能会导致创建对话框时崩溃。比如图标、样式表等资源缺失或加载失败,都会影响对话框的正常创建和显示。在DLL加载时,需要确保资源被正确注册,可使用`QResource::registerResource`函数来加载资源文件,示例代码如下: ```cpp #include <QResource> bool loadResources() { return QResource::registerResource("your_resource.rcc"); } ``` ### 线程安全问题 如果在DLL中的函数是在非主线程中调用,而`QDialog`对象的创建和显示必须在主线程中进行,否则会导致崩溃。因为Qt的GUI操作不是线程安全的,在非主线程中进行GUI操作可能会破坏Qt的内部状态。可以通过信号槽机制将创建和显示对话框的操作转移到主线程中,示例代码如下: ```cpp #include <QCoreApplication> #include <QDialog> #include <QThread> #include <QMetaObject> class DialogSignal : public QObject { Q_OBJECT public: explicit DialogSignal(QObject *parent = nullptr) : QObject(parent) {} signals: void showDialogSignal(); }; void showDialogInDll() { static DialogSignal signal; static bool connected = false; if (!connected) { QObject::connect(&signal, &DialogSignal::showDialogSignal, []() { QDialog *a = new QDialog; a->show(); }); connected = true; } QMetaObject::invokeMethod(&signal, [&]() { emit signal.showDialogSignal(); }, Qt::QueuedConnection); } ``` ### 内存管理问题 确保`QDialog`对象的内存管理正确,避免对象被重复释放或在未初始化时被使用。例如,不要在函数返回前手动删除`QDialog`对象,除非你有特殊的内存管理需求。若在DLL中创建的对话框对象被意外删除,后续对该对象的操作会导致崩溃。 ### 元对象系统问题 确保DLL和主程序使用相同版本的Qt库,并且在编译DLL和主程序时使用相同的编译器和编译选项。不同版本的Qt库或编译选项可能会导致元对象系统冲突,从而引发崩溃。因为元对象系统是Qt实现信号槽、属性系统等功能的基础,不一致的配置会破坏其正常运行。 ### 父窗口问题 `QDialog`对象的父窗口设置不当也可能导致崩溃。如果父窗口已经被销毁,而对话框仍然引用该父窗口,会出现问题。可以根据实际情况设置合适的父窗口或不设置父窗口。例如: ```cpp // 创建无父窗口的对话框 QDialog *a = new QDialog(nullptr); a->show(); ``` ### 名称冲突问题 如同引用[1]中提到的情况,名称冲突可能导致崩溃。如果DLL中的类名、函数名等与主程序或其他库中的名称冲突,可能会引发意外的错误。可以将相关名称换成其他名称进行测试,看是否能解决问题。 ### Qt源码内部问题 在某些情况下,可能是Qt源码内部的问题导致崩溃。例如引用[1]中提到的`QWindowsWindow::destroyWindow()`里`QWindowsContext::instance()`为空崩溃的情况。这可能是由于Qt库本身的bug或者与特定环境的兼容性问题导致的。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值