QUdpSocket client{} 可以调用带默认参数的构造函数。原问题的错误是把形参声明写进了实参列表:QObject *parent = nullptr 用来声明函数参数,不能放在创建对象的花括号里。
先区分声明和调用
跳转到“先区分声明和调用”Qt 的构造函数接口可简化为:
explicit QUdpSocket(QObject *parent = nullptr); // 声明:参数类型、名字和默认值创建对象时传入表达式:
QUdpSocket first{}; // 省略参数,使用默认的 nullptrQUdpSocket second{nullptr}; // 显式传入空指针下面这一行是错误示例,不能编译:
QUdpSocket client{QObject *parent = nullptr}; // 实参位置出现了参数声明默认参数使调用方可以省略相应实参;花括号初始化并不禁止默认参数。默认成员初始化器与构造函数初始化列表都可以使用,选择取决于是否需要当前构造函数的参数。C++ 列表初始化规则、Qt QUdpSocket 构造函数
类成员的两种写法
跳转到“类成员的两种写法”固定初始化状态可以直接写在声明处:
class Receiver { QUdpSocket client{};};需要依赖构造函数参数或所属对象时,使用成员初始化列表。若同一个成员已有默认成员初始化器,构造函数中显式写出的初始化器优先;不是先默认构造一次再赋值。C++ 基类和成员初始化
QWidget 和 QUdpSocket 的完整例子
跳转到“QWidget 和 QUdpSocket 的完整例子”下面的程序验证两种成员写法,以及 QObject 父子关系。它不打开窗口,可作为编译检查;实际显示窗口时再调用 show() 和应用事件循环。
// main.cpp;C++17,链接 Qt6::Widgets、Qt6::Network#include <QApplication>#include <QUdpSocket>#include <QWidget>#include <cassert>
class Receiver : public QWidget {public: explicit Receiver(QWidget *parent = nullptr) : QWidget(parent), ownedClient(this) {}
QUdpSocket independentClient{}; QUdpSocket ownedClient;};
int main(int argc, char *argv[]) { QApplication app(argc, argv); Receiver receiver; assert(receiver.independentClient.parent() == nullptr); assert(receiver.ownedClient.parent() == &receiver);}这里没有新增信号、槽或属性,因此不需要为了继承 QWidget 而额外写 Q_OBJECT。两个 socket 都是成员对象,其存储寿命由 Receiver 管理;不能对成员地址执行 delete。
QWidget 构造函数接收 QWidget*,所以 Receiver 的 parent 也使用 QWidget*。任意 QObject* 并不一定指向 QWidget,不能直接交给 QWidget(parent)。反方向则可行:QWidget 派生自 QObject,this 能传给接受 QObject* 的 QUdpSocket。QWidget 构造函数
parent 应该是谁
跳转到“parent 应该是谁”ownedClient(this) 表示 socket 属于当前接收器;ownedClient(parent) 则把它挂到接收器的父对象,二者不是同一种所有权关系。
本例成员会在 QWidget 基类析构前被自动析构,并从 QObject 的子对象列表移除,所以父对象随后不会重复删除它。这个结论不能推广为“任意栈对象都可以随意设置 parent”:对外部局部对象重新设置父对象时,必须保证析构顺序,不让父对象先删除仍将自动析构的局部对象。Qt 对象树与所有权
若 socket 需要跟随接收器移动到其他线程,父子关系也影响线程归属;QWidget 自身应留在 GUI 线程。异步网络设计应另行选择工作对象和线程模型。
排错顺序
跳转到“排错顺序”- 看花括号里是否是值或表达式,而不是
类型 名字 = 默认值。 - 核对目标构造函数接收的确切指针类型。
- 确认对象是成员、局部变量还是动态分配对象,再决定 parent。
- 不要用在构造函数体内赋值来代替不可复制 QObject 成员的初始化。
原始问题保留于 CSDN 记录,本页纠正了原回答对花括号初始化和 QWidget 参数类型的解释。