Qt 中类的 前向声明 和#include的区别

118 篇文章 8 订阅

Qt中类的前向声明和#include的区别

~ 七、Qt中的前向声明

【Qt】类前置声明

要点:

1. 主要指在头文件中,再包含了其他的头文件?

2. 前向声明,可以加快编译的速度,但存在使用上的一些限制条件,不如 #include 可靠。

在2014年,G 内部有一篇总结性文章指出了前置声明将造成的十种危险。最终C++ Code Style经历了一个过渡期之后全面倒向了#include。 https://www.zhihu.com/question/63201378  
G 内部有超大规模的分布式编译集群『Forge』。哪怕是十万以上的target,全部build一遍也就是几分钟的事情。

注:

1. 有人说:有 G程序员说,只用 #include就好了,可靠。
问题是:当自己的、程序庞大、或电脑速度慢的场景,#include法,就是在浪费资源,浪费生命。

自己也想只用 #include 呀,但是,没有超大规模的分布式编译集群,怎么办呢?是选择使用前置声明?还是选择浪费生命?前向声明 和#include,过度使用,两种都会走向极端。

2. Qt 自带的官方类,在用户的使用过程中不会修改,使用预编译头文件的方法,也可以实现 前置声明 的类似编译速度吗?

3. 一个前置声明的例子?

service.h

#ifndef SERVICE_H
#define SERVICE_H

#include "ui_service.h"

#include <QDialog>
//此类以独立于平台和协议的方式保存蓝牙地址。
QT_FORWARD_DECLARE_CLASS(QBluetoothAddress)                       

原文链接:https://blog.csdn.net/TM1695648164/article/details/120828227

4. 用户自定义类,例子 ?

5. 在官方手册上,查不到这个用法啊 ?

QT5.3 did not support "forward declaration"??(Solved)

  https://forum.qt.io/topic/44284/qt5-3-did-not-support-forward-declaration-solved/5

注:主要是要关切编译速度,才需要考虑前置声明?

ylkevin 2014年7月31日 11:07

QT += widgets. is already included.
forward declaration is not supported as:

//#include <QtGui>
//class QCheckBox;
//class QLabel;
//class QLineEdit;
//class QPushButton;

must be replaced by:

#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>
#include <QCheckBox>
#include <QHBoxLayout>

QT4.82 support forward declaration, QT5.3 doesn't.

As a side note (作为旁注)a forward declaration is a C++ feature not Qt hence(因此) Qt cannot support nor not support it.

All these classes were indirectly (间接)defined in QtGui before Qt5.
In Qt5 they belong to QtWidgets

So if you would forward declare class QLabel in a header and then include file QLabel or QtWidgets in a source file everything would work.

Qt例子学习笔记 - /Examples/Qt-6.2.0/bluetooth/btscanner  https://blog.csdn.net/TM1695648164/article/details/120828227

从这个例子来看:Qt 6 也在用前置声明 ?并没有被淘汰 ?

//此类以独立于平台和协议的方式保存蓝牙地址。
QT_FORWARD_DECLARE_CLASS(QBluetoothAddress)

6. 在官方文件 qglobal.h中找到以下定义:

#ifdef __cplusplus

#include <algorithm>

#if !defined(QT_NAMESPACE) || defined(Q_MOC_RUN) /* user namespace */

# define QT_PREPEND_NAMESPACE(name) ::name
# define QT_USE_NAMESPACE
# define QT_BEGIN_NAMESPACE
# define QT_END_NAMESPACE
# define QT_BEGIN_INCLUDE_NAMESPACE
# define QT_END_INCLUDE_NAMESPACE
#ifndef QT_BEGIN_MOC_NAMESPACE
# define QT_BEGIN_MOC_NAMESPACE
#endif
#ifndef QT_END_MOC_NAMESPACE
# define QT_END_MOC_NAMESPACE
#endif
# define QT_FORWARD_DECLARE_CLASS(name) class name;
# define QT_FORWARD_DECLARE_STRUCT(name) struct name;
# define QT_MANGLE_NAMESPACE(name) name

#else /* user namespace */

--------------------------------------------------------

关联参考:

 Qt 中类的 前向声明 和#include的区别 https://blog.csdn.net/ken2232/article/details/136126779

C++前置声明 和 #include   https://blog.csdn.net/ken2232/article/details/136126609

================================

QT_FORWARD_DECLARE_CLASS 是神马意思?

  https://bbs.csdn.net/topics/370071446

在qt 的一个叫 40000 chips 的例子里面一开始有几行QT_FORWARD_DECLARE_CLASS 是神马意思? 和 include有神马区别?

#ifndef MAINWINDOW_H

 #define MAINWINDOW_H

 #include <QtGui/qwidget.h>

 QT_FORWARD_DECLARE_CLASS(QGraphicsScene)

 QT_FORWARD_DECLARE_CLASS(QGraphicsView)

 QT_FORWARD_DECLARE_CLASS(QLabel)

 QT_FORWARD_DECLARE_CLASS(QSlider)

 QT_FORWARD_DECLARE_CLASS(QSplitter)

 class MainWindow : public QWidget

 {

     Q_OBJECT

 public:

     MainWindow(QWidget *parent = 0);

 private:

     void setupMatrix();

     void populateScene();

     QGraphicsScene *scene;

     QSplitter *h1Splitter;

     QSplitter *h2Splitter;

 };

 #endif


facat 2011-07-20
 其实就是前置声明而已
jyinkailej 2011-07-17

在qglobal.h中找到以下定义:

# define QT_FORWARD_DECLARE_CLASS(name) class name
// 直接用:class name,不是更直接符合 C++风格吗 ?

// 还是说 qt 内部有其他的联动编译机制,需要使用 QT_FORWARD_DECLARE_CLASS(name) 这种语法 ?


这就说明 和 C++ 头文件里的 一样

qter_wd007 2011-07-16

应该是与类前置声明类似的东西。不过奇怪的是,在帮助中找不到相关的说明。

比如第一行可以改作:class QGraphicsScene;

你也可以使用包含语句:include <QtGui/QGraphicsScene>

c++/Qt/前置声明/QT_FORWARD_DECLARE_CLASS

QT_FORWARD_DECLARE_CLASS <->Qt 中的前置声明类

我们在学习Qt自带的demo时,很多时候会看到这个宏,也就是c++的前置声明宏

在学习过程中我们会有以下疑问?

1.什么是前置声明?

前置声明:即类、函数和模板的声明,无定义.

2.为什么要使用前置声明?前置声明有什么优点、缺点?

①因为前置声明可以节省编译时间。

②优点: #include 会使编译器展开对应头文件的所有内容进行编译。
    前置声明只需要编译你用到的部分(一般是一个指针,指向你所指的内容部分)即可。

③缺点:当你修改了源码时,可能不重新编译你所修改的内容。所以,我们在写一些库,或者一些大型一点的工程,基本不建议使用前置声明

3.一定要用么?可以不用吗?如果不用前置声明的话,怎么做会比较安全?

不一定。可以,如果不用前置声明的话,你需要在你的*.h文件里用#include添加你需要类、函数或模板头文件即可。

tips

不是很熟悉的程序猿尽可能地避免使用前置声明。使用 #include 包含需要的头文件即可。 

原文链接:https://blog.csdn.net/qq_42815643/article/details/123471057

Qt 中类的 前向声明  和#include的区别

文章目录

    1. 头文件引入类的两种方法
    1. 它们的区别是什么?

1. 头文件引入类的两种方法

在头文件中引入另一个类经常有两种写法:

class Name;

#include “Name.h”

2. 它们的区别是什么?

第一种叫做前向声明

在程序中引入了类类型为Name.在声明之后,定义之前,类Name是一个不完全类型(incompete type),即已知Name是一个类型,但不知道包含哪些成员.

不完全类型只能以有限方式使用,不能定义该类型的对象,

不完全类型只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数.(前向声明只知道有这么一个类,但具体信息无从得知);

此外,它可以去除编译依赖,减少编译消耗的时间(如果使用#include “Name.h” 一旦Name的定义需要修改,Name.h也就会重新编译,导致所有用到Name.h的文件也需要重新编译,这样就造成了编译依赖,增加了编译的时间,在大型项目中,如果很多这样的地方的话,甚至可能极度增加编译时间。)

  

第二种include头文件则是将整个该头文件与使用到的地方关联起来

所以你可以知道该类的具体信息。 在编译的时候把Name.h文件直接展开,所以里面的接口都能用,可以申明对象,调用方法。

~ 七、Qt中的前向声明

  https://blog.csdn.net/chchlh/article/details/18312571

一、定义与例子:     

可以声明一个类而不定义它。这个声明,有时候被称为前向声明(forward declaration)。

    不完全类型只能以有限方式使用,不能定义该类型的对象,不完全类型只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数。

    举个Qt的例子:

在头文件myDialog.h中:

    #ifndef MYDIALOG_H
    #define MYDIALOG_H
     
    #include <QtWidgets/QDialog>
    #include "ui_mydialog.h"
     
    class QCheckBox;
    class QLabel;
    class QLineEdit;
    class QPushButton;
     
    class MyDialog : public QDialog
    {
        Q_OBJECT
     
    public:
        MyDialog(QWidget *parent = 0);
        ~MyDialog();
    signals:
        void findNext(const QString *str, Qt::CaseSensitivity cs);
        void findPrevious(const QString *str, Qt::CaseSensitivity cs);
     
    private:
        Ui::MyDialogClass ui;
        QLabel *label;
        QlineEdit *lineEdit;
        QCheckBox *caseCheckBox;
        QCheckBox *backwardCheckBox;
        QPushButton *findButton;
        QPushButton *closeButton;
    private slots:
        void findClicked();
        void enableFindButton(const QString &text);
    };
     
    #endif // MYDIALOG_H

    class QCheckBox;
    class QLabel;
    class QLineEdit;
    class QPushButton;

其中:

class QCheckBox;
class QLabel;
class QLineEdit;
class QPushButton;

是前向声明,不写的话是编译不过的,因为编译器不知道这些类是否存在。简单来说,所谓前向声明就是告诉编译器,我要用这几个类,而且这几个类存在,你就不要担心它们存不存在的问题啦!

二、使用的原因

  • 第一,众所周知,避免头文件的循环引用。
  • 第二,就是避免引入头文件。

三、使用的情景

    我记不清类的详细信息(忘记尺寸,位置,成员),但我可以告诉你,我的类是什么(编译器占位符,有一个类型,之后进行补全)!仅通过名字不能使用它的,但可以写个前向声明标示这个类的存在。
                       
原文链接:https://blog.csdn.net/chchlh/article/details/18312571

【Qt】类前置声明

在Qt开发项目中,经常会用到各种库,但是一般在.h文件中进行某类型变量定义时,都会对其类型的class进行声明,如下面代码所示:

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
     
    #include <QMainWindow>
    #include <QCloseEvent>
     
    class QLineEdit;
    class QDialog;
     
    namespace Ui {
    class MainWindow;
    }
     
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
     
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
     
    public:
        void newFile();
        bool maybeSave();
        bool save();
        bool saveAs();
        bool saveFile(const QString &fileName);
        bool loadFile(const QString &fileName);
     
    private slots:
        void on_actionNew_triggered();
        void on_actionOpen_triggered();
        void on_actionClose_triggered();
        void on_actionSave_triggered();
        void on_actionSaveAs_triggered();
        void on_actionExit_triggered();
        void on_actionUndo_triggered();
        void on_actionCut_triggered();
        void on_actionCopy_triggered();
        void on_actionPaste_triggered();
     
    private:
        Ui::MainWindow *ui;
     
        bool isUntitled;
        QString curFile;
        
        QLineEdit *findLineEdit;
        QDialog *findDlg;
     
    protected:
        void closeEvent(QCloseEvent *event);
    };
     
    #endif // MAINWINDOW_H

前置声明的类定义:

    class QLineEdit;
    class QDialog;

对象的定义:

     QLineEdit *findLineEdit;
     QDialog *findDlg;

 
作用:

它们会告诉编译器,我们用到的这些类已经存在了,并且不需要知道这些类的完整定义。

 
原因:

我们为什么要这样做,而不是将它们的头文件包含进来呢?这主要是由于在程序下文中,我们只是简单的定义了指向这些类的对象的指针,而并没有涉及到该类的其他方面。

 
优势:

1、是避免了头文件被其他文件多次包含,尤其是在头文件中包含头文件时,容易造成重复包含和产生包含顺序问题,并且增大了文件的体积;

2、提高了编译速度,因为编译器只需知道该类已经被定义了,而无需了解定义的细节。
                       
原文链接:https://blog.csdn.net/sunriver2000/article/details/82819755

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值