首先需要回顾一下cpp命名空间知识;
扩展命名空间:
一个文件中书写了两个相同名字的命名空间,第二个命名将作为第一个命名空间的补充
例如:
第一个Ui命名空间是一个前置声明;第二个Ui是具体定义,就跟函数声明和函数名义一模一样
以上代码等价于一下代码:
进入正题:
ui_xxxx.h文件
有一个命名空间Ui,其中定义了一个类MainWindow继承字Ui_MainWindow,这样就具有UI_MainWindow所有特征了。
其中还有两个宏QT_BEGIN_NAMESPACE与QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
:
- 这是一个Qt框架中的宏,它标志着命名空间的开始。它实际上被定义为
{
。 - 使用这个宏的目的是为了确保Qt库中的所有声明都在正确的命名空间中。这是为了避免全局命名冲突,因为Qt可能涉及大量的符号和名称。
namespace Ui { class MainWindow; }
:
- 在
QT_BEGIN_NAMESPACE
和QT_END_NAMESPACE
之间,定义了一个名为Ui
的命名空间,并在其中声明了一个名为MainWindow
的类。这是一个前向声明,通常在头文件中,以避免包含整个类的定义,从而提高编译速度。
QT_END_NAMESPACE
:
- 这是另一个Qt宏,它标志着命名空间的结束。它实际上被定义为
}
。 - 与
QT_BEGIN_NAMESPACE
一样,这个宏确保在正确的位置结束命名空间。
总体来说,这段代码的目的是定义了一个名为Ui
的命名空间,其中包含了一个名为MainWindow
的类的前向声明。这通常是在Qt的UI文件中使用的,以便在C++代码中使用UI设计工具创建的窗口类而不需要包含整个UI文件的定义。这有助于减少编译时间和降低代码耦合。(chatgpt的解释)
MainWindow.h文件
MainWindow.cpp文件
我们来一步一步合并代码:
首先#include "mainwindow.h"会将mainwindow.h文件内容直接复制到cpp文件
所以代码如下:
同理根据:#include "ui_mainwindow.h"
代码过长不给图片了
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> //第一个命名空间 QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif #ifndef UI_MAINWINDOW_H #define UI_MAINWINDOW_H #include <QtCore/QVariant> #include <QtWidgets/QApplication> #include <QtWidgets/QListView> #include <QtWidgets/QMainWindow> #include <QtWidgets/QMenuBar> #include <QtWidgets/QStatusBar> #include <QtWidgets/QWidget> QT_BEGIN_NAMESPACE class Ui_MainWindow { public: QWidget *centralwidget; QListView *listView; QMenuBar *menubar; QStatusBar *statusbar; void setupUi(QMainWindow *MainWindow) { if (MainWindow->objectName().isEmpty()) MainWindow->setObjectName("MainWindow"); MainWindow->resize(800, 600); centralwidget = new QWidget(MainWindow); centralwidget->setObjectName("centralwidget"); listView = new QListView(centralwidget); listView->setObjectName("listView"); listView->setGeometry(QRect(130, 80, 256, 192)); MainWindow->setCentralWidget(centralwidget); menubar = new QMenuBar(MainWindow); menubar->setObjectName("menubar"); menubar->setGeometry(QRect(0, 0, 800, 21)); MainWindow->setMenuBar(menubar); statusbar = new QStatusBar(MainWindow); statusbar->setObjectName("statusbar"); MainWindow->setStatusBar(statusbar); retranslateUi(MainWindow); QMetaObject::connectSlotsByName(MainWindow); } // setupUi void retranslateUi(QMainWindow *MainWindow) { MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr)); } // retranslateUi }; //扩展命名空间 namespace Ui { class MainWindow: public Ui_MainWindow {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_MAINWINDOW_H MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; }
再次合并两个相同的命名字的命名空间(并删除无用的代码)
合并后
#include <QMainWindow> #include <QtCore/QVariant> #include <QtWidgets/QApplication> #include <QtWidgets/QListView> #include <QtWidgets/QMainWindow> #include <QtWidgets/QMenuBar> #include <QtWidgets/QStatusBar> #include <QtWidgets/QWidget> class Ui_MainWindow { public: QWidget *centralwidget; QListView *listView; QMenuBar *menubar; QStatusBar *statusbar; void setupUi(QMainWindow *MainWindow) { if (MainWindow->objectName().isEmpty()) MainWindow->setObjectName("MainWindow"); MainWindow->resize(800, 600); centralwidget = new QWidget(MainWindow); centralwidget->setObjectName("centralwidget"); listView = new QListView(centralwidget); listView->setObjectName("listView"); listView->setGeometry(QRect(130, 80, 256, 192)); MainWindow->setCentralWidget(centralwidget); menubar = new QMenuBar(MainWindow); menubar->setObjectName("menubar"); menubar->setGeometry(QRect(0, 0, 800, 21)); MainWindow->setMenuBar(menubar); statusbar = new QStatusBar(MainWindow); statusbar->setObjectName("statusbar"); MainWindow->setStatusBar(statusbar); retranslateUi(MainWindow); QMetaObject::connectSlotsByName(MainWindow); } void retranslateUi(QMainWindow *MainWindow) { MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr)); } }; //合并后的样子 namespace Ui { class MainWindow; class MainWindow: public Ui_MainWindow {}; } class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; }
这样子就能看懂了吧,在MainWindow.h里面声明的UI命名空间是一个前置声明,防止因为找不到Ui而在编译的时候报错,因为#inlcude "ui_xxx.h"并不在MainWindow.h里面是在MainWindow.cpp文件中,而编译的时候只会在本文件内中查询是否存在该命名空间,所以需要一个前置声明,当然你也可以直接把写在MainWindow.cpp的#include "ui_xxx.h"复制到MainWindow.h文件中,但是QtCreator默认就是把#include "ui_xxx.h"放在MainWindow.cpp文件中