Search code examples
c++linuxqtg++initializer-list

How to use an initializer list on a derived class?


I'm writing a Qt application where I have a derived class of QDialog. My derived class also uses a initializer list to for a couple of private members (that get set through the constructor). Now I am a bit confused even in terms of allowed syntax. I found this post, tried to follow it in my little demo script and came up with the following:

#include <QString>
#include <QSettings>
#include <QtWidgets/QWidget>
#include <QtWidgets/QDialog>

class foo : QDialog 
{
    Q_OBJECT
    public:
        foo(QSettings* const set=nullptr, const QString s="", QWidget *parent=nullptr) :  QDialog{
        public:
            foo(QSettings* const set=nullptr, const QString s="", QWidget *parent): QDialog(parent){}
        };
        QString nme_get() {return name;}
        void qux(void);
        
    private:
         const QString name;
         QSettings * const settings; 
};

void foo::qux(void) {
    QSettings *test = settings;
    QString name = nme_get();
    test->beginGroup(name);
    /*
     * ...
    */
    test->endGroup();
}


int main (void) {
    QWidget *parent = nullptr;
    QSettings *sttngs = new QSettings(QSettings::NativeFormat,QSettings::UserScope,"GNU","scaper",nullptr
);
    foo inst{sttngs, QString("quux"), parent};
    inst.qux();
        
    return 0;    
}

which the compiler throws out with:

foo.cpp: In constructor ‘foo::foo(QSettings*, QString, QWidget*)’:
foo.cpp:12:9: error: expected primary-expression before ‘public’
         public:
         ^
foo.cpp:12:9: error: expected ‘}’ before ‘public’
foo.cpp:12:9: error: no matching function for call to ‘QDialog::QDialog(<brace-enclosed initializer list>)’
In file included from /usr/include/x86_64-linux-gnu/qt5/QtWidgets/QDialog:1:0,
                 from foo.cpp:4:
/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h:93:5: note: candidate: QDialog::QDialog(QDialogPrivate&, QWidget*, Qt::WindowFlags)
     QDialog(QDialogPrivate &, QWidget *parent, Qt::WindowFlags f = 0);
     ^
/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h:93:5: note:   candidate expects 3 arguments, 1 provided
/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h:54:14: note: candidate: QDialog::QDialog(QWidget*, Qt::WindowFlags)
     explicit QDialog(QWidget *parent = 0, Qt::WindowFlags f = 0);
              ^
/usr/include/x86_64-linux-gnu/qt5/QtWidgets/qdialog.h:54:14: note:   conversion of argument 1 would be ill-formed:
foo.cpp:11:9: error: uninitialized const member in ‘class QSettings* const’ [-fpermissive]
         foo(QSettings* const set=nullptr, const QString s="", QWidget *parent=nullptr) :  QDialog{
         ^
foo.cpp:21:28: note: ‘QSettings* const foo::settings’ should be initialized
          QSettings * const settings; 
                            ^
foo.cpp:12:9: error: expected ‘{’ before ‘public’
         public:

I understand that the error appears due to me not submitting the type to the base class correctly but I'm not sure how to modify it to make it work... Also on https://doc.qt.io/qt-5/qdialog.html it says: QDialog(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()) and the compiler says: qdialog.h:93:5: note: candidate: QDialog::QDialog(QDialogPrivate&, QWidget*, Qt::WindowFlags) - which confuses me, am I using the wrong headerfile?


Solution

  • When defining c++ classes, the general idea is to have the class methods declared and documented in an header file (.h file), and implemented in a cpp file. I am writing this code without an editor at the moment so there may be some syntax errors, but it will get you headed in the right direction:

    In the h file:

    #include <QString>
    #include <QSettings>
    #include <QtWidgets/QWidget>
    #include <QtWidgets/QDialog>
    
    class foo : public QDialog 
    {
        Q_OBJECT
        public:
            foo(QSettings* const set=nullptr, const QString s="", QWidget *parent=nullptr);
            QString nme_get();
            void qux(); //Removed the void parameter here
    
        private:
             const QString name;
             QSettings * const settings; 
    };
    

    In the cpp file:

    // Or whatever your h file is named
    #include "foo.h" 
    
    foo::foo(QSettings* const set=nullptr, const QString s="", QWidget *parent=nullptr)
        :QDialog(parent) {
        // Do constructor stuff here (like initializing name for instance)
    }
    
    void foo::nme_get() {
        return name;
    }
    
    void foo::qux() {
        QSettings *test = settings;
        QString name = nme_get();
        test->beginGroup(name);
        /*
         * ...
        */
        test->endGroup();
    }