唐山企業(yè)建網(wǎng)站山東seo推廣公司
qt-C++筆記之自定義繼承類初始化時涉及到parents的初始化
code review!
參考筆記
1.qt-C++筆記之父類窗口、父類控件、對象樹的關系
2.qt-C++筆記之繼承自 QWidget和繼承自QObject 并通過 getWidget() 顯示窗口或控件時的區(qū)別和原理
3.qt-C++筆記之自定義類繼承自 QObject
與 QWidget
及開發(fā)方式詳解
4.qt-C++筆記之自定義繼承類初始化時涉及到parents的初始化
文章目錄
- qt-C++筆記之自定義繼承類初始化時涉及到parents的初始化
- 一.聲明和實現(xiàn)在一起
- 1. 構造函數(shù)中傳遞 `parent`
- 2. 父類 `parent` 的作用
- 3. 子類中未顯式初始化父類 `parent` 的情況
- 4. 動態(tài)設置父對象
- 5. 使用智能指針管理對象
- 6. 完整示例
- 二.聲明和實現(xiàn)分開
- 1. 頭文件(聲明部分)
- 2. 源文件(實現(xiàn)部分)
- 3. 完整示例
- 頭文件(`MyWidget.h`)
- 源文件(`MyWidget.cpp`)
- 主程序(`main.cpp`)
- 4. 關鍵點解析
- 1. 頭文件中聲明構造函數(shù)
- 2. 源文件中通過初始化列表傳遞 `parent`
- 3. 使用 Qt 的對象樹
- 4. 在構造函數(shù)中初始化子對象
- 5. 運行效果
- 6. 總結
在 Qt 的 C++ 開發(fā)中,當我們創(chuàng)建一個類繼承自 Qt 的某個類(比如
QObject
或者
QWidget
)時,通常需要在構造函數(shù)中對父類的
parent
指針進行初始化。這是 Qt 的對象樹管理機制的核心部分之一。
Qt 中的對象樹通過 parent
指針來自動管理對象的生命周期。當一個父對象被銷毀時,它會自動銷毀所有的子對象。因此,合理地設置 parent
是很重要的。
以下是如何在繼承類中初始化父類的 parent
的一些說明和示例:
一.聲明和實現(xiàn)在一起
1. 構造函數(shù)中傳遞 parent
當定義自己的繼承類時,可以在構造函數(shù)中接受一個 parent
參數(shù),并將其傳遞給父類的構造函數(shù)。
#include <QWidget>class MyWidget : public QWidget {
public:explicit MyWidget(QWidget *parent = nullptr) : QWidget(parent) // 調(diào)用父類的構造函數(shù),初始化 parent{// 其他初始化代碼}
};
在上面的代碼中:
MyWidget
是從QWidget
繼承的。- 構造函數(shù)接受一個
QWidget *parent
參數(shù),并將其傳遞給QWidget
的構造函數(shù)來初始化父類的parent
。
2. 父類 parent
的作用
parent
參數(shù)的作用是將當前對象附加到指定的父對象上,從而形成一個 Qt 對象樹。例如:
QWidget *mainWindow = new QWidget;
MyWidget *childWidget = new MyWidget(mainWindow); // 設置 mainWindow 為 parent
在這種情況下:
mainWindow
是父對象。childWidget
被添加為mainWindow
的子對象。- 當
mainWindow
被銷毀時,childWidget
會被自動銷毀。
3. 子類中未顯式初始化父類 parent
的情況
如果子類沒有顯式初始化父類的 parent
參數(shù),默認情況下,Qt 對象的父類指針會被設置為 nullptr
:
class MyWidget : public QWidget {
public:MyWidget() {// 未顯式傳遞 parent,parent 默認為 nullptr}
};
這意味著:
- 對象不會自動附加到任何父對象。
- 必須手動管理該對象的生命周期。
4. 動態(tài)設置父對象
即使在構造函數(shù)中沒有傳遞 parent
,也可以通過調(diào)用 setParent
方法在運行時動態(tài)設置父對象:
MyWidget *childWidget = new MyWidget;
childWidget->setParent(mainWindow); // 動態(tài)設置 parent
這種方法在需要在對象創(chuàng)建后再決定其父對象時非常有用。
5. 使用智能指針管理對象
如果你不想依賴 Qt 的對象樹,也可以使用標準的 C++ 智能指針(如 std::unique_ptr
或 std::shared_ptr
)來管理對象的生命周期。但是,如果使用智能指針,就不要設置 parent
,以免 Qt 和智能指針同時試圖管理對象的生命周期,導致潛在的問題。
6. 完整示例
以下是一個完整的例子,展示如何正確初始化和使用 parent
:
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>class MyWidget : public QWidget {
public:explicit MyWidget(QWidget *parent = nullptr): QWidget(parent) // 初始化父類的 parent{QVBoxLayout *layout = new QVBoxLayout(this);QPushButton *button = new QPushButton("Click Me", this);layout->addWidget(button);setLayout(layout);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);QWidget *mainWindow = new QWidget;MyWidget *childWidget = new MyWidget(mainWindow);mainWindow->resize(400, 300);mainWindow->show();return app.exec();
}
在這個例子中:
MyWidget
是一個自定義的QWidget
子類。MyWidget
的父對象是mainWindow
。- 當
mainWindow
被銷毀時,MyWidget
也會被自動銷毀。
二.聲明和實現(xiàn)分開
當我們在 C++ 中將繼承類的聲明和實現(xiàn)分離時,涉及到 Qt 的 parent
初始化時,依然需要通過構造函數(shù)初始化列表在實現(xiàn)文件中將 parent
參數(shù)傳遞給父類的構造函數(shù)。以下是詳細的分離步驟和示例。
1. 頭文件(聲明部分)
在頭文件中聲明類及構造函數(shù),通常會為 parent
參數(shù)提供一個默認值(通常為 nullptr
),這樣在使用時可以選擇是否顯式傳遞父對象。
#ifndef MYWIDGET_H
#define MYWIDGET_H#include <QWidget>class MyWidget : public QWidget {Q_OBJECT // 如果使用信號和槽機制,必須添加 Q_OBJECT 宏public:// 構造函數(shù)聲明,帶 parent 參數(shù),默認值為 nullptrexplicit MyWidget(QWidget *parent = nullptr);// 其他成員函數(shù)聲明(如果有)
};#endif // MYWIDGET_H
2. 源文件(實現(xiàn)部分)
在源文件中實現(xiàn)構造函數(shù)時,使用初始化列表將 parent
參數(shù)傳遞給父類的構造函數(shù)。
#include "MyWidget.h"// 構造函數(shù)實現(xiàn)
MyWidget::MyWidget(QWidget *parent): QWidget(parent) // 將 parent 傳遞給 QWidget 的構造函數(shù)
{// 在這里編寫其他初始化代碼
}
3. 完整示例
以下是一個完整的例子,展示了如何分離聲明和實現(xiàn),同時正確初始化 parent
。
頭文件(MyWidget.h
)
#ifndef MYWIDGET_H
#define MYWIDGET_H#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>class MyWidget : public QWidget {Q_OBJECTpublic:explicit MyWidget(QWidget *parent = nullptr); // 構造函數(shù)聲明private:QVBoxLayout *layout; // 布局管理器QPushButton *button; // 按鈕
};#endif // MYWIDGET_H
源文件(MyWidget.cpp
)
#include "MyWidget.h"// 構造函數(shù)實現(xiàn)
MyWidget::MyWidget(QWidget *parent): QWidget(parent) // 將 parent 傳遞給父類 QWidget 的構造函數(shù)
{// 初始化布局和按鈕layout = new QVBoxLayout(this); // 將布局設置為當前 MyWidget 的子對象button = new QPushButton("Click Me", this); // 將按鈕設置為當前 MyWidget 的子對象layout->addWidget(button); // 將按鈕添加到布局中setLayout(layout); // 應用布局到當前 widget
}
主程序(main.cpp
)
#include <QApplication>
#include "MyWidget.h"int main(int argc, char *argv[]) {QApplication app(argc, argv);QWidget *mainWindow = new QWidget; // 創(chuàng)建主窗口MyWidget *childWidget = new MyWidget(mainWindow); // 將 mainWindow 作為 parentmainWindow->resize(400, 300);mainWindow->show(); // 顯示主窗口return app.exec();
}
4. 關鍵點解析
1. 頭文件中聲明構造函數(shù)
explicit MyWidget(QWidget *parent = nullptr);
- 使用
explicit
關鍵字可以防止隱式類型轉換。 parent
參數(shù)的默認值為nullptr
,這樣在不需要父對象時可以直接創(chuàng)建孤立的對象。
2. 源文件中通過初始化列表傳遞 parent
MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
QWidget(parent)
是父類構造函數(shù)的調(diào)用,它會將parent
初始化為當前對象的父對象。- 這是遵循 C++ 的構造函數(shù)初始化列表的標準寫法。
3. 使用 Qt 的對象樹
通過傳遞 parent
,可以讓 MyWidget
成為其父對象的一部分,Qt 的對象樹將自動管理子對象的生命周期。例如:
- 如果
MyWidget
的父對象是mainWindow
,銷毀mainWindow
會自動銷毀其所有子對象,包括MyWidget
。
4. 在構造函數(shù)中初始化子對象
在 MyWidget
的構造函數(shù)中,布局和按鈕都通過 new
創(chuàng)建,并將當前對象(this
)作為它們的父對象:
layout = new QVBoxLayout(this); // 布局的父對象是 MyWidget
button = new QPushButton("Click Me", this); // 按鈕的父對象是 MyWidget
這確保了這些子對象會被 MyWidget
自動管理,無需手動釋放。
5. 運行效果
運行上述程序后:
mainWindow
是主窗口。MyWidget
是主窗口的子對象。- 當你關閉
mainWindow
時,MyWidget
會被自動銷毀。 - 按鈕和布局也會被自動銷毀,因為它們是
MyWidget
的子對象。
6. 總結
- 在繼承類中,通常需要在構造函數(shù)中通過調(diào)用父類的構造函數(shù)來初始化
parent
。 - 合理設置
parent
可以讓 Qt 對象樹自動管理對象的生命周期。 - 如果不使用
parent
,需要手動管理對象的生命周期。 - 動態(tài)設置
parent
或結合智能指針管理對象是可行的,但需要小心避免沖突。 - 在聲明與實現(xiàn)分離時,
parent
的初始化通過構造函數(shù)的初始化列表實現(xiàn)。 - 在頭文件中聲明構造函數(shù)時,可以為
parent
提供默認值nullptr
。 - 在源文件中通過
: QWidget(parent)
調(diào)用父類構造函數(shù)進行初始化。 - 合理使用 Qt 的對象樹機制,可以自動管理對象的生命周期,簡化內(nèi)存管理。