跳转到内容
新建笔记

C++ 成员初始化:默认参数、花括号与 Qt parent

QUdpSocket client{} 可以调用带默认参数的构造函数。原问题的错误是把形参声明写进了实参列表:QObject *parent = nullptr 用来声明函数参数,不能放在创建对象的花括号里。

Qt 的构造函数接口可简化为:

explicit QUdpSocket(QObject *parent = nullptr); // 声明:参数类型、名字和默认值

创建对象时传入表达式:

QUdpSocket first{}; // 省略参数,使用默认的 nullptr
QUdpSocket 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 构造函数

ownedClient(this) 表示 socket 属于当前接收器;ownedClient(parent) 则把它挂到接收器的父对象,二者不是同一种所有权关系。

本例成员会在 QWidget 基类析构前被自动析构,并从 QObject 的子对象列表移除,所以父对象随后不会重复删除它。这个结论不能推广为“任意栈对象都可以随意设置 parent”:对外部局部对象重新设置父对象时,必须保证析构顺序,不让父对象先删除仍将自动析构的局部对象。Qt 对象树与所有权

若 socket 需要跟随接收器移动到其他线程,父子关系也影响线程归属;QWidget 自身应留在 GUI 线程。异步网络设计应另行选择工作对象和线程模型。

  1. 看花括号里是否是值或表达式,而不是 类型 名字 = 默认值。
  2. 核对目标构造函数接收的确切指针类型。
  3. 确认对象是成员、局部变量还是动态分配对象,再决定 parent。
  4. 不要用在构造函数体内赋值来代替不可复制 QObject 成员的初始化。

原始问题保留于 CSDN 记录,本页纠正了原回答对花括号初始化和 QWidget 参数类型的解释。