Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. forward declarations give errors + I want some explanation
QtWS25 Last Chance

forward declarations give errors + I want some explanation

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 4 Posters 2.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    SweetOrange
    wrote on 20 Jan 2016, 19:06 last edited by SweetOrange
    #1

    Hi I am using the find example from "C++ Gui programming with Qt" book chapter 2.
    There is the file finddialog.h :

    #ifndef FINDDIALOG_H
    #define FINDDIALOG_H
    
    #include <QDialog>
    
    class QCheckBox;
    class QLabel;
    class QLineEdit;
    class QPushButton;
    
    class FindDialog : public QDialog
    {
        Q_OBJECT
    
    public:
        FindDialog(QWidget *parent = 0);
    
    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
    
    

    I get errors with the class forward declarations at beginning of code.
    http://s13.postimg.org/jilgxzcsn/1_20_2016a.jpg

    I have included in project file the line

    QT      += widgets
    

    finddialog.cpp:

    #include <QtGui>
    
    #include "finddialog.h"
    
    FindDialog::FindDialog(QWidget *parent)
        : QDialog(parent)
    {
        label = new QLabel(tr("Find &what:"));
        lineEdit = new QLineEdit;
        label->setBuddy(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"));
    
        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()));
    
        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());
    }
    
    void FindDialog::findClicked()
    {
        QString text = lineEdit->text();
        Qt::CaseSensitivity cs =
                caseCheckBox->isChecked() ? Qt::CaseSensitive
                                          : Qt::CaseInsensitive;
        if (backwardCheckBox->isChecked()) {
            emit findPrevious(text, cs);
        } else {
            emit findNext(text, cs);
        }
    }
    
    void FindDialog::enableFindButton(const QString &text)
    {
        findButton->setEnabled(!text.isEmpty());
    }
    
    

    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();
    }
    
    

    find.pro:

    QT      += widgets
    
    TEMPLATE      = app
    HEADERS       = finddialog.h
    SOURCES       = finddialog.cpp \
                    main.cpp
    
    1 Reply Last reply
    0
    • M Offline
      M Offline
      mrjj
      Lifetime Qt Champion
      wrote on 20 Jan 2016, 19:10 last edited by
      #2

      hi
      when you say
      class QLabel;
      its ok to use it for pointers.

      QLabel *myname;

      But if you start to use ANYTHING in it
      like
      myname->setBuddy

      then a forward is NOT enough and u must include the include file for it
      #include <QLabel>

      So that is what incomplete class error means.

      as you only tell it the name. and if u use more than name, you must give compiler the full class definition.

      S 1 Reply Last reply 20 Jan 2016, 20:06
      2
      • V Offline
        V Offline
        ValentinMichelet
        wrote on 20 Jan 2016, 20:05 last edited by
        #3

        In addition to what @mrjj said, it's a good practice to use forward declaration in your .h file, but you have to add #include <QLabel> in your .cpp for the reasons mrjj gave you. Indeed, the compiler is complaining about your .cpp file, not your .h file.

        But for instance, if you don't use a pointer for your variable, or if you inherit from an other class, then you have to #include it, since the compiler needs to know extra information about the content of the class.

        1 Reply Last reply
        0
        • M mrjj
          20 Jan 2016, 19:10

          hi
          when you say
          class QLabel;
          its ok to use it for pointers.

          QLabel *myname;

          But if you start to use ANYTHING in it
          like
          myname->setBuddy

          then a forward is NOT enough and u must include the include file for it
          #include <QLabel>

          So that is what incomplete class error means.

          as you only tell it the name. and if u use more than name, you must give compiler the full class definition.

          S Offline
          S Offline
          SweetOrange
          wrote on 20 Jan 2016, 20:06 last edited by SweetOrange
          #4

          @mrjj
          I added the #includes at finddialog.h:

          #ifndef FINDDIALOG_H
          #define FINDDIALOG_H
          
          #include <QDialog>
          #include <QCheckBox>
          #include <QLabel>
          #include <QLineEdit>
          #include <QPushButton>
          
          class QCheckBox;
          class QLabel;
          class QLineEdit;
          class QPushButton;
          
          class FindDialog : public QDialog
          {
              Q_OBJECT
          
          public:
              FindDialog(QWidget *parent = 0);
          
          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
          
          

          Do I need the forward declarations anymore?

          Also I get the errors:
          http://s11.postimg.org/4izv8mff7/1_20_2016b.jpg
          which I suspect that I haven't included the include files for QHBoxLayout and QVBoxLayout.
          In which file do I include these?

          V 1 Reply Last reply 20 Jan 2016, 20:08
          0
          • S SweetOrange
            20 Jan 2016, 20:06

            @mrjj
            I added the #includes at finddialog.h:

            #ifndef FINDDIALOG_H
            #define FINDDIALOG_H
            
            #include <QDialog>
            #include <QCheckBox>
            #include <QLabel>
            #include <QLineEdit>
            #include <QPushButton>
            
            class QCheckBox;
            class QLabel;
            class QLineEdit;
            class QPushButton;
            
            class FindDialog : public QDialog
            {
                Q_OBJECT
            
            public:
                FindDialog(QWidget *parent = 0);
            
            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
            
            

            Do I need the forward declarations anymore?

            Also I get the errors:
            http://s11.postimg.org/4izv8mff7/1_20_2016b.jpg
            which I suspect that I haven't included the include files for QHBoxLayout and QVBoxLayout.
            In which file do I include these?

            V Offline
            V Offline
            ValentinMichelet
            wrote on 20 Jan 2016, 20:08 last edited by ValentinMichelet
            #5

            @SweetOrange

            Look at the file on the right of the error message, you'll know where to #include what the compiler lacks.

            1 Reply Last reply
            1
            • M Offline
              M Offline
              mrjj
              Lifetime Qt Champion
              wrote on 20 Jan 2016, 20:08 last edited by
              #6

              Hi in 99% of all cases the include has same name as class.
              #include <QVBoxLayout>
              and no, no need for forward when u use the real include.

              1 Reply Last reply
              1
              • V Offline
                V Offline
                ValentinMichelet
                wrote on 20 Jan 2016, 20:22 last edited by
                #7

                Maybe it's a bit technical, but here is a link on Stack Overflow explaining what a forward declaration is:
                http://stackoverflow.com/questions/553682/when-can-i-use-a-forward-declaration

                Basically, a forward declaration is only a "Don't worry compiler, this class exists." statement. As soon as the implementation of the class is required, the #include is mendatory.

                The question of "should I use #include or forward declaration here?" is off topic tho.

                1 Reply Last reply
                1
                • S Offline
                  S Offline
                  SweetOrange
                  wrote on 20 Jan 2016, 20:35 last edited by
                  #8

                  Thanks for the info.

                  #ifndef FINDDIALOG_H
                  #define FINDDIALOG_H
                  
                  #include <QDialog>
                  #include <QLabel>
                  #include <QLineEdit>
                  #include <QCheckBox>
                  #include <QPushButton>
                  
                  //class QCheckBox;
                  //class QLabel;
                  //class QLineEdit;
                  //class QPushButton;
                  
                  class FindDialog : public QDialog
                  {
                      Q_OBJECT
                  
                  public:
                      FindDialog(QWidget *parent = 0);
                  
                  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
                  
                  
                  #include <QtGui>
                  
                  #include "finddialog.h"
                  #include <QHBoxLayout>
                  #include <QVBoxLayout>
                  
                  
                  
                  
                  
                  
                  FindDialog::FindDialog(QWidget *parent)
                      : QDialog(parent)
                  {
                      label = new QLabel(tr("Find &what:"));
                      lineEdit = new QLineEdit;
                      label->setBuddy(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"));
                  
                      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()));
                  
                      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());
                  }
                  
                  void FindDialog::findClicked()
                  {
                      QString text = lineEdit->text();
                      Qt::CaseSensitivity cs =
                              caseCheckBox->isChecked() ? Qt::CaseSensitive
                                                        : Qt::CaseInsensitive;
                      if (backwardCheckBox->isChecked()) {
                          emit findPrevious(text, cs);
                      } else {
                          emit findNext(text, cs);
                      }
                  }
                  
                  void FindDialog::enableFindButton(const QString &text)
                  {
                      findButton->setEnabled(!text.isEmpty());
                  }
                  
                  
                  #include <QApplication>
                  
                  #include "finddialog.h"
                  
                  int main(int argc, char *argv[])
                  {
                      QApplication app(argc, argv);
                      FindDialog *dialog = new FindDialog;
                      dialog->show();
                      return app.exec();
                  }
                  

                  Now works and compiles properly and runs.

                  Some explanations though that I found the book lacks. What does the header of the constructor means in finddialog.cpp ?

                  FindDialog::FindDialog(QWidget *parent)
                      : QDialog(parent)
                  

                  This is class inheritance as far as I understand it

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on 20 Jan 2016, 20:38 last edited by
                    #9

                    Hi
                    FindDialog::FindDialog(QWidget *parent)
                    : QDialog(parent) <---- here we call base class constructor with the parent.

                    This is need to setup the part of the class we get from the base class.

                    if u have
                    class A :B

                    then some of A is from B and it might need to do stuff in its constructor.
                    so we call it also.

                    1 Reply Last reply
                    1
                    • S Offline
                      S Offline
                      SweetOrange
                      wrote on 20 Jan 2016, 20:53 last edited by
                      #10

                      Tell me if I am wrong...

                      QDialog is derived from QWidget.

                      The FindDialog constructor is typical of Qt widget classes. The parent parameter specifies the parent widget. The default is a null pointer meaning that the dialog has no parent

                      when we have

                      FindDialog::FindDialog(QWidget *parent)
                         : QDialog(parent)
                      

                      we just say that QDialog is the parent of FindDialog and as mentioned above QWidget is the parent of QDialog.

                      V 1 Reply Last reply 20 Jan 2016, 21:07
                      0
                      • S SweetOrange
                        20 Jan 2016, 20:53

                        Tell me if I am wrong...

                        QDialog is derived from QWidget.

                        The FindDialog constructor is typical of Qt widget classes. The parent parameter specifies the parent widget. The default is a null pointer meaning that the dialog has no parent

                        when we have

                        FindDialog::FindDialog(QWidget *parent)
                           : QDialog(parent)
                        

                        we just say that QDialog is the parent of FindDialog and as mentioned above QWidget is the parent of QDialog.

                        V Offline
                        V Offline
                        ValentinMichelet
                        wrote on 20 Jan 2016, 21:07 last edited by ValentinMichelet
                        #11

                        @SweetOrange

                        Just to be sure that you don't mix up "C++ parent class" and "Qt parent mechanism".

                        In pure C++, a class can inherit from a parent class:

                        class QDialog: public QWidget {}
                        

                        Here the QDialog inherits from QWidget.

                        In Qt, there is a mechanism that makes your life easier for memory managment. You give your class a parent to let it handle the memory in destruction. If you code in C++, you may know that there is no garbage collector as there is in other languages (Java for instance). So as soon as you create an object dynamically - on the heap - using "new" operator, you are responsible for it's destruction using "delete". Qt enables you not to worry about deletion: give your object a parent, and the memory will be handle at its destruction.

                        FindDialog::FindDialog(QWidget *parent): QDialog(parent)
                        

                        Here we call the parent constructor (QDialog) with the parent parameter and we let Qt handle destruction, as well as a provide a way to potential future inherited classes to enjoy this mechanism.

                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on 20 Jan 2016, 21:22 last edited by
                          #12

                          Hi,

                          To add to my fellows, you should move:

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

                          in your implementation file. That's were they are needed in your case.

                          Note that you are using #include <QtGui>, while good for rapid prototyping it's a module wide include which means it will pull in all headers from said module thus your compilation time will increase since all files are going to be parsed.

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          0

                          1/12

                          20 Jan 2016, 19:06

                          • Login

                          • Login or register to search.
                          1 out of 12
                          • First post
                            1/12
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved