[solved]multiple definitions of ...



  • Hi. I have 2 cllasses that include a header file called database.h. It looks like this:

    dialog.cpp:

    // ...
    #include "dialog.h"
    #include "database.h"
    #include "add.h"
    // ...
    

    add.cpp:

    // ...
    #include "add.h"
    #include "database.h"
    // ...
    

    database.h

    // ...
    namespace MyDataBase {
    Two variables in here;
    
    Three functions in here(with definitions);
    }
    // ...
    

    All three of them have macros:

    #ifndef ...
    #define ...
    #endif
    

    I get 5 error of multiple definitions of every variable and function in database.h.
    It starts working when I remove database.h form add.cpp. What is the problem ?


  • Moderators

    @killerman
    One needs a crystal ball with the details you are giving. For a sound answer you need to share also the error message and possible other information.

    Stabbing into the fog: Possibly you have actual inline methods in the header file, but you have forgotten to use the keyword "inline".



  • Adding inline did not help but it works fine after I removed namespace from database.h.

    Anyone knows why ?

    For more info I've uploaded whole project in here:
    https://www.dropbox.com/sh/p9rfwc8za439wi5/AADryEvjDeOn30SCykSoTRYea?dl=0


  • Moderators

    @killerman
    database.h:

    #ifndef DATABASE
    #define DATABASE
    
    #include <QtCore>
    #include <QtSql>
    #include <QMessageBox>
    
    // namespace MyDataBase {
    extern    QSqlDatabase db;
    extern    QString table;
    
    inline void connectDataBase(QString hn, QString dbn, QString user, QString pass, QString tab){
            table = tab;
    
            db = QSqlDatabase::addDatabase("QMYSQL");
            db.setHostName(hn);
            db.setDatabaseName(dbn);
            db.setUserName(user);
            db.setPassword(pass);
    
            if( !db.open() ){
                QMessageBox::information(NULL, "DB ERROR", db.lastError().text());
            }
        }
    
    inline void getEverything(QSqlRelationalTableModel *model){
            model->setTable(table);
            model->select();
        }
    
    inline void dodaj(QString tyt, QString aut, int str, QString data, QString form){
            QSqlQuery qry;
            qry.exec( QString("INSERT INTO people(tytul, autor, liczbastron, dataukonczenia, format) "
                      "VALUES ('%1', '%2', '%3', '%4', '%5')")
                      .arg(tyt).arg(aut).arg(str).arg(data).arg(form));
        }
    // }
    
    #endif // DATABASE
    

    dialog.cpp

    #include "dialog.h"
    #include "ui_dialog.h"
    
    #include "database.h"
    #include "dodaj.h"
    
    #include <QDebug>
    
    QSqlDatabase db;
    QString table;
    
    Dialog::Dialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog)
    {
        ui->setupUi(this);
    
        /*MyDataBase::*/connectDataBase("localhost", "ksiazki", "root", "", "books");
    
        model = new QSqlRelationalTableModel;
        /*MyDataBase::*/getEverything(model);
    
        ui->tableView->setModel(model);
        ui->tableView->resizeColumnsToContents();
    
        model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
        model->setHeaderData(1, Qt::Horizontal, QObject::tr("Tytul"));
        model->setHeaderData(2, Qt::Horizontal, QObject::tr("Autor"));
        model->setHeaderData(3, Qt::Horizontal, QObject::tr("Liczba stron"));
        model->setHeaderData(4, Qt::Horizontal, QObject::tr("Data ukonczenia"));
        model->setHeaderData(5, Qt::Horizontal, QObject::tr("Format"));
    }
    
    Dialog::~Dialog()
    {
        delete ui;
    }
    
    void Dialog::on_pushButton_clicked()
    {
        // DODAJ
        Dodaj okienko;
        okienko.exec();
    }
    

    At least it does compile and link. Possibly it may even working now.

    A couple of recommendations:
    You should separate source code and declarations.
    Global variables shall not be declared as you had done in the database header. Removal brought up the next problem, because they are present in every module you are using the header.
    The inlines were missing and they are required as you have "programmed".


  • Moderators

    You've got global variables defined in a header:

    namespace MyDataBase {
        QSqlDatabase db;
        QString table;
    

    Then you've also got functions defined.

    When you include that header in multiple cpps they are instantiated in each of them and then linker is giving you an error.
    You should only declare functions in headers. Definitions should go into a cpp.
    Global variables are evil in their own way. Move them to cpp and make functions returning them exposed in the header. If you don't want to do that then you can mark the variables with extern and then move the definition of them to cpp.

    In short:

    //database.h
    ...
    namespace MyDataBase {
       extern QSqlDatabase db;
       extern QString table;
       void connectDataBase(QString hn, QString dbn, QString user, QString pass, QString tab);
    ...
    
    //database.cpp
    //include "database.h"
    namespace MyDataBase {
       QSqlDatabase db;
       QString table;
       void connectDataBase(QString hn, QString dbn, QString user, QString pass, QString tab) {
          ...
       }
    


  • Thanks for help :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.