1

I have a header file, header.h, which contains all of my classes, the functions associated with them, and supplemental header files (<QDebug>, <QString>, and so forth). The only file that uses header.h is my main window, mainwindow.h. However, for every function in my header.h, there is an error that appears in Qt Creator under Issues as follows (where in_cards::use_card() is the example function):

 In function `ZN8in_cards8use_card()`               [moc_mainwindow.o]
 multiple definition of `in_cards::use_card()`      [header.h]          258
 first defined here                                 [header.h]          258

I have already checked the .pro file as suggested in other questions and none of the .cpp, .h, or .ui files are duplicated.

Any suggestions or a step in the right direction would be appreciated.

EDIT: Here are the contents of both header files.

header.h:

#ifndef HEADER_H
#define HEADER_H

#include <QDebug>
#include <QIntValidator>
#include <QItemDelegate>
#include <QLineEdit>
#include <QString>
#include <QStringList>
#include <QTextEdit>
#include <QVector>
#include <QWidget>

// - - - - - C P U  C L A S S - - - - -
class cpu
{
    private:
        int ac;
        int ir;
        int pc;

    public:
        // C O N S T R U C T O R S
        cpu() :
            ac (0),
            ir (0),
            pc (0) { }

        // D E S T R U C T O R S
        ~cpu() { }

        // G E T T E R S
        int get_ac() const { return ac; }
        int get_ir() const { return ir; }
        int get_pc() const { return pc; }

        // S E T T E R S
        bool set_ac(int a);
        bool set_ir(int i);
        bool set_pc(int p);

        // P R I N T E R S
        QString print_ac();
        QString print_ir();
        QString print_pc();

        // O T H E R
        bool increment_pc();
};

// S E T T E R S

bool cpu::set_ac(int a)
{
    if(a >= -999 && a <= 999)
    {
        ac = a;
        return true;
    }

    return false;
}

bool cpu::set_ir(int i)
{
   if(i >= 0 && i <= 999)
   {
       ir = i;
       return true;
   }

   return false;
}

bool cpu::set_pc(int p)
{
    if(p >= 0 && p <= 99)
    {
        pc = p;
        return true;
    }

    return false;
}

// P R I N T E R S
QString cpu::print_ac()
{
    QString print;
    int     a = ac;

    if(a < 0)
    {
        a = a * -1;
        print = "-";
    }

    if(a <= 9)
    {
        print = print + "00" + (QString::number(a));
    }
    else if(a <= 99)
    {
        print = print + "0" + (QString::number(a));
    }
    else if(a <= 999)
    {
        print = print + (QString::number(a));
    }
    else
    {
        print = "err";
    }

    return print;
}

QString cpu::print_ir()
{
    QString print;
    int     i = ir;

    if(i <= 9)
    {
        print = "00" + (QString::number(i));
    }
    else if(i <= 99)
    {
        print = "0" + (QString::number(i));
    }
    else if(i <= 999)
    {
        print = (QString::number(i));
    }
    else
    {
        print = "err";
    }

    return print;
}

QString cpu::print_pc()
{
    QString print;
    int     p = pc;

    if(p <= 9)
    {
        print = "0" + (QString::number(p));
    }
    else if(p <= 99)
    {
        print = (QString::number(p));
    }
    else
    {
        print = "err";
    }

    return print;
}

// O T H E R

bool cpu::increment_pc()
{
    if(pc != 99)
    {
        pc++;
        return true;
    }

    return false;
}

// - - - - - I N P U T  C A R D  C L A S S - - - - -
struct in_card
{
    int  value;
    bool used;
    bool empty;

    void set_value(int v)  { value = v; }
    void set_used (bool u) { used  = u; }
    void set_empty(bool e) { empty = e; }
};

class in_cards
{
    private:
        QVector<in_card> cards;

    public:
        // C O N S T R U C T O R S
        in_cards();

        // D E S T R U C T O R S
        ~in_cards() { }

        // S E T T E R S
        void set_card(int loc,
                      int val);

        // C H E C K E R S
        bool card_available();

        // G E T T E R S
        int use_card();
        QVector<int>     get_as_ints   ();
        QVector<QString> get_as_strings();


};

// C O N S T R U C T O R S
in_cards::in_cards()
{
    for(int i = 0; i < 15; i++)
    {
        in_card new_card;

        new_card.value = 1000;
        new_card.used = false;
        new_card.empty = true;

        cards.push_back(new_card);
    }
}

// S E T T E R S

void in_cards::set_card(int loc, int val)
{
    cards[loc].set_value(val);
    cards[loc].set_used(false);
    cards[loc].set_empty(false);
}

// C H E C K E R S

bool in_cards::card_available()
{
    for(int i = 0; i < cards.size(); i++)
    {
        if(cards.at(i).used == false)
        {
            return true;
        }
    }

    return false;
}

// G E T T E R S

int in_cards::use_card()
{
    for(int i = 0; i < cards.size(); i++)
    {
        if(cards.at(i).used == false)
        {
            if(cards.at(i).empty == false)
            {
                cards[i].set_used(true);

                return cards.at(i).value;
            }
            else
            {
                return 1000;
            }
        }
    }
}

QVector<int> in_cards::get_as_ints()
{
    QVector<int> values;

    for(int i = 0; i < cards.size(); i++)
    {
        values.push_back(cards.at(i).value);
    }

    return values;
}

// - - - - - O U T P U T  C A R D  C L A S S - - - - -
class out_cards
{
    private:
        QVector<int> cards;

    public:
        // C O N S T R U C T O R S
        out_cards() { }

        // D E S T R U C T O R S
        ~out_cards() { }

        // S E T T E R S
        bool set_card(int c);

        // G E T T E R S
        QVector<int>     get_as_ints   () { return cards; }
        QVector<QString> get_as_strings();
};

// S E T T E R S

bool out_cards::set_card(int c)
{
    if(c >= -999 && c <= 999)
    {
        cards.push_back(c);

        return true;
    }

    return false;
}

// - - - - - M E M O R Y  C L A S S - - - - -
struct mem_cell
{
    int  value;
    bool empty;

    void set_value(int v) { value = v; }
    void set_empty(bool e) { empty = e; }
};

class memory
{
    private:
        QVector<mem_cell> cells;

    public:
        // C O N S T R U C T O R S
        memory();

        // D E S T R U C T O R S
        ~memory() { }

        // G E T T E R S
        int get_value_at(int v) const { return cells.at(v).value; }
        QVector<int> get_as_ints();
        bool get_empty_at(int e) const { return cells.at(e).empty; }

        // S E T T E R S
        void set_cell(int loc, int val) { cells[loc].set_value(val); cells[loc].set_empty(false); }
};

// C O N S T R U C T O R S
memory::memory()
{
    for(int i = 0; i < 100; i++)
    {
        mem_cell new_cell;

        new_cell.value = 1000;
        new_cell.empty = true;

        cells.push_back(new_cell);
    }
}

// G E T T E R S
QVector<int> memory::get_as_ints()
{
    QVector<int> values;

    for(int i = 0; i < 100; i++)
    {
        values.push_back(cells.at(i).value);
    }

    return values;
}

#endif

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "header.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);

    void format_all();

    void format_inputTable();

    void format_outputTable();

    void setup_run();

    ~MainWindow();

private slots:

    void on_runButton_clicked();

    void on_clearInputButton_clicked();

    void on_clearOutputButton_clicked();

    void on_clearAllButton_clicked();

private:
    Ui::MainWindow *ui;

    cpu the_cpu;
    in_cards the_in_cards;
    out_cards the_out_cards;
    memory the_memory;
};

#endif
4
  • is your header guarded ? Commented Nov 2, 2015 at 23:59
  • @KostasRim Yes, header.h and mainwindow.h both use #ifndef, #define, and #endif. Commented Nov 3, 2015 at 0:02
  • can you post them ? my answer is wrong then, i will edit later.. Commented Nov 3, 2015 at 0:03
  • @KostasRim Yes, I have updated the question to contain the full contents of both header files. Commented Nov 3, 2015 at 0:07

3 Answers 3

2

While in many cases separating an implementation into a source file is a good idea, header-only libraries are also a common approach. So what went wrong here?

The proximate cause of your issue was that, while you may have included header.h just once (or rather, written only one source file that #included it via mainwindow.h), it was included again by the source file constructed by moc from your mainwindow.h (hence the moc_mainwindow.o in the error message).

While your header.h would have worked if it really had been used only once, the correct thing to do (beyond the header guards that prevent problems when one translation unit includes the same header more than once) is to declare your functions inline. The keyword need not appear on every function: it's unnecessary for function templates (or member functions of class templates) and is implied when a member function is defined inside the class definition.

Sign up to request clarification or add additional context in comments.

Comments

1

For every header in your project do the following: suppose your header is called myheader

#ifndef MYHEADER_H
#define MYHEADER_H

//your declerations go here
#endif

solution:

A header file is nothing more than a ''text'' file. The preproccessor will just copy paste your header code. In headers you declare the functions and in .cpp files you define them. Change the code and seperate definitions from declarations and you code will compile.

4 Comments

wow wow wow, you have defined the functions in the header ? there is no header.cpp ?
Yes, for now. Originally, each class had its own header and source files but I put everything in one file after I got the multiple definition errors just to make sure that I wasn't accidentally including duplicate headers.
a header file is nothing more than a ''text'' file. The preproccessor will just copy paste your header code. In headers you declare the functions and in .cpp files you define them. Change the code and seperate definitions from declarations and you code will compile. Something irrelevant your get methods should be const :P post a comment when you make the change. I am waiting. :)
Welp, that apparently fixed it. Thanks a bunch! Keeping this up just in case I run into a problem, though.
0

I also received this error, but for a different reason.

executing qmake solved it for me.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.