我有一个头文件 header.h
,它包含我的所有类,与它们相关的函数以及补充头文件( <QDebug>
, <QString>
等) . 唯一使用 header.h
的文件是我的主窗口 mainwindow.h
. 但是,对于 header.h
中的每个函数,Qt Creator中出现的错误如下所示(其中 in_cards::use_card()
是示例函数):
In function `ZN8in_cards8use_card()` [moc_mainwindow.o]
multiple definition of `in_cards::use_card()` [header.h] 258
first defined here [header.h] 258
我已经按照其他问题的建议检查了.pro文件,并没有重复.cpp,.h或.ui文件 .
任何建议或朝正确方向迈出的一步都将受到赞赏 .
编辑:这是两个头文件的内容 .
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
2 回答
对于项目中的每个 Headers ,请执行以下操作:假设您的 Headers 名为myheader
解:
头文件只不过是一个“文本”文件 . preproccessor将只复制粘贴您的 Headers 代码 . 在 Headers 中,您声明函数,并在.cpp文件中定义它们 . 更改代码并从声明中分离定义,您将编译代码 .
虽然在许多情况下将实现分离到源文件是个好主意,但是仅标头库也是一种常见的方法 . 那么这里出了什么问题?
问题的原因在于,虽然您可能只包含了一次
header.h
(或者更确切地说,只通过mainwindow.h
只写了一个源文件#include
),但mainwindow.h
构造的源文件再次包含它mainwindow.h
错误消息中的moc_mainwindow.o
) .虽然
header.h
如果真的只使用过一次就会起作用,但 correct 要做的事情(除了防止一个翻译单元多次包含相同 Headers 时出现问题的 Headers 保护)就是声明你的函数inline
. 关键字不需要出现在每个函数上:它不需要函数模板(或类模板的成员函数),并且在类定义中定义成员函数时隐含 .