首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Qt 專案原始碼結構分析:標頭檔與實作檔的職責劃分

     編輯:關於C++

良好的 Qt 專案架構要求標頭檔(.h)與實作檔(.cpp)職責分明。本文以經典 FindDialog 範例,詳細解析各檔案應包含的內容與設計原則。

標頭檔:FindDialog.h —— 介面宣告與前向宣告

#ifndef FINDDIALOG_H
#define FINDDIALOG_H

#include <QtGui/QDialog>  // 基類定義(必要)

// 前向宣告:減少編譯相依、加速編譯
class QCheckBox;
class QLabel;
class QLineEdit;
class QPushButton;

class FindDialog : public QDialog {
    Q_OBJECT  // Qt 元物件系統宏(訊號/槽、屬性、RTTI)

public:
    explicit FindDialog(QWidget *parent = nullptr);  // explicit 防隱性轉換
    ~FindDialog();  // 解構函式宣告(若需自訂清理)

signals:  // 訊號:供外部連接
    void findNext(const QString &str, Qt::CaseSensitivity cs);
    void findPrevious(const QString &str, Qt::CaseSensitivity cs);

private slots:  // 私有槽:內部邏輯回應
    void findClicked();
    void enableFindButton(const QString &text);

private:  // 實作細節:僅標頭檔可見
    QLabel *label;
    QLineEdit *lineEdit;
    QCheckBox *caseCheckBox;
    QCheckBox *backwardCheckBox;
    QPushButton *findButton;
    QPushButton *closeButton;
};

#endif // FINDDIALOG_H

標頭檔設計原則

  1. 防禦性包含:僅包含必要基類定義(QDialog),其餘使用前向宣告。
  2. 最小介面暴露:公開介面僅限建構子、解構子、訊號;實作細節(子元件指標、槽函式)置於 private。
  3. Qt 宏正確使用:Q_OBJECT 必須放在類別定義首行,啟用 MOC 處理。
  4. Const 正確性:參數傳遞優先使用 const T&,避免不必要複製。

主程式:main.cpp —— 程式進入點

#include <QApplication>
#include "finddialog.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);  // 應用程式物件(單例)
    FindDialog *dialog = new FindDialog;
    dialog->show();  // 非模態顯示
    return app.exec();  // 進入事件迴圈
}

實作檔:FindDialog.cpp —— 具體邏輯實現

#include <QtGui>  // 模組整體包含(Qt4 風格),Qt5 建議精確包含
#include "finddialog.h"

FindDialog::FindDialog(QWidget *parent) : QDialog(parent) {
    // 1. 建立子元件
    label = new QLabel(tr("Find &what:"));
    lineEdit = new QLineEdit;
    label->setBuddy(lineEdit);  // 伙伴關係:Alt+W 聚焦 lineEdit

    caseCheckBox = new QCheckBox(tr("Match &case"));
    backwardCheckBox = new QCheckBox(tr("Search &backward"));
    findButton = new QPushButton(tr("&Find"));
    findButton->setDefault(true);
    findButton->setEnabled(false);
    closeButton = new QPushButton(tr("Close"));

    // 2. 訊號/槽連接
    connect(lineEdit, SIGNAL(textChanged(const QString&)),
            this, SLOT(enableFindButton(const QString&)));
    connect(findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
    connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));

    // 3. 版面配置
    QHBoxLayout *topLeftLayout = new QHBoxLayout;
    topLeftLayout->addWidget(label);
    topLeftLayout->addWidget(lineEdit);

    QVBoxLayout *leftLayout = new QVBoxLayout;
    leftLayout->addLayout(topLeftLayout);
    leftLayout->addWidget(caseCheckBox);
    leftLayout->addWidget(backwardCheckBox);

    QVBoxLayout *rightLayout = new QVBoxLayout;
    rightLayout->addWidget(findButton);
    rightLayout->addWidget(closeButton);
    rightLayout->addStretch();  // 底部彈性空間

    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->addLayout(leftLayout);
    mainLayout->addLayout(rightLayout);
    setLayout(mainLayout);  // 設定對話框主版面

    setWindowTitle(tr("Find"));
    setFixedHeight(sizeHint().height());  // 固定高度
}

FindDialog::~FindDialog() {
    // 子元件由 Qt 父子機制自動刪除,通常無需手動 delete
}

void FindDialog::findClicked() {
    QString text = lineEdit->text();
    Qt::CaseSensitivity cs = caseCheckBox->isChecked()
                           ? Qt::CaseInsensitive : Qt::CaseSensitive;

    if (backwardCheckBox->isChecked())
        emit findPrevious(text, cs);
    else
        emit findNext(text, cs);
}

void FindDialog::enableFindButton(const QString &text) {
    findButton->setEnabled(!text.isEmpty());
}

實作檔關鍵點

  • 包含順序:系統/Qt 標頭檔 → 專案標頭檔,避免隱性相依。
  • 父子關係:new QWidget(parent) 建立所有權,父物件銷毀時自動清理子物件。
  • 國際化:所有可見字串包裹 tr(),支援多語系。
  • 版面管理:使用佈局類別而非絕對座標,自適應字體、DPI、視窗大小。
  • 新式連接語法:Qt5 建議 connect(sender, &Sender::signal, receiver, &Receiver::slot) 編譯期檢查。

執行結果

現代 Qt (Qt5/6) 改進建議

  1. 精確包含:#include <QDialog>、#include <QLabel> 等,替代 <QtGui>。
  2. 使用 nullptr 替代 0。
  3. 採用新式訊號/槽語法(函式指標),獲得編譯期型別安全。
  4. 考慮 QScopedPointer / std::unique_ptr 管理非 Qt 物件資源。
  5. 使用 uic 處理 .ui 檔案,分離 UI 描述與邏輯程式碼。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved