构建文件夹中的 Qt 创建者多重定义
Posted
技术标签:
【中文标题】构建文件夹中的 Qt 创建者多重定义【英文标题】:Qt creator multiple definition within build folder 【发布时间】:2016-05-11 19:44:39 【问题描述】:我在 Qt 创建者那里收到一条奇怪的错误消息,这根本不知道为什么会发生它。我目前正在为 Ludo 模拟器编写一个 AI 播放器,该模拟器已被编写为 QT gui。我创建了一个名为 player_q_learning
的 C++ 类,但由于某种原因,在 build 文件夹中创建了 moc_player_q_learning.cpp
,并创建了我已经在 player_q_learning
中定义的函数的多个定义......为什么我会遇到这个错误?
/home/Vato/Desktop/ludo-gui/build-ludo-Desktop-Debug/moc_player_q_learning.cpp:116: error: multiple definition of `player_q_learning::calc_input(float*, int, int)'
ludo.pro
#-------------------------------------------------
#
# Project created by QtCreator 2016-03-15T10:40:30
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ludo
TEMPLATE = app
SOURCES += main.cpp\
dialog.cpp \
game.cpp \
ludo_player.cpp \
ludo_player_random.cpp \
player_q_learning.cpp
HEADERS += dialog.h \
game.h \
ludo_player.h \
positions_and_dice.h \
ludo_player_random.h \
player_q_learning.h
FORMS += dialog.ui
CONFIG += object_with_source
QMAKE_CXXFLAGS += -std=c++11 -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -Wunused
main.cpp
#include "dialog.h"
#include <QApplication>
#include "game.h"
#include <vector>
#include "ludo_player.h"
#include "ludo_player_random.h"
#include "positions_and_dice.h"
Q_DECLARE_METATYPE( positions_and_dice )
using namespace std;
int main(int argc, char *argv[])
QApplication a(argc, argv);
qRegisterMetaType<positions_and_dice>();
//instanciate the players here
ludo_player p1, p2;
ludo_player_random p3, p4;
game g;
g.setGameDelay(010); //if you want to see the game, set a delay
// Add a GUI <-- remove the '/' to uncomment block
// Dialog w;
// QObject::connect(&g,SIGNAL(update_graphics(std::vector<int>)),&w,SLOT(update_graphics(std::vector<int>)));
// QObject::connect(&g,SIGNAL(set_color(int)), &w,SLOT(get_color(int)));
// QObject::connect(&g,SIGNAL(set_dice_result(int)), &w,SLOT(get_dice_result(int)));
// QObject::connect(&g,SIGNAL(declare_winner(int)), &w,SLOT(get_winner(int)));
// w.show();
//Or don't add the GUI
//QObject::connect(&g,SIGNAL(close()),&a,SLOT(quit()));
//*/
//set up for each player
QObject::connect(&g, SIGNAL(player1_start(positions_and_dice)),&p1,SLOT(start_turn(positions_and_dice)));
QObject::connect(&p1,SIGNAL(select_piece(int)), &g, SLOT(movePiece(int)));
QObject::connect(&g, SIGNAL(player1_end(std::vector<int>)), &p1,SLOT(post_game_analysis(std::vector<int>)));
QObject::connect(&p1,SIGNAL(turn_complete(bool)), &g, SLOT(turnComplete(bool)));
QObject::connect(&g, SIGNAL(player2_start(positions_and_dice)),&p2,SLOT(start_turn(positions_and_dice)));
QObject::connect(&p2,SIGNAL(select_piece(int)), &g, SLOT(movePiece(int)));
QObject::connect(&g, SIGNAL(player2_end(std::vector<int>)), &p2,SLOT(post_game_analysis(std::vector<int>)));
QObject::connect(&p2,SIGNAL(turn_complete(bool)), &g, SLOT(turnComplete(bool)));
QObject::connect(&g, SIGNAL(player3_start(positions_and_dice)),&p3,SLOT(start_turn(positions_and_dice)));
QObject::connect(&p3,SIGNAL(select_piece(int)), &g, SLOT(movePiece(int)));
QObject::connect(&g, SIGNAL(player3_end(std::vector<int>)), &p3,SLOT(post_game_analysis(std::vector<int>)));
QObject::connect(&p3,SIGNAL(turn_complete(bool)), &g, SLOT(turnComplete(bool)));
QObject::connect(&g, SIGNAL(player4_start(positions_and_dice)),&p4,SLOT(start_turn(positions_and_dice)));
QObject::connect(&p4,SIGNAL(select_piece(int)), &g, SLOT(movePiece(int)));
QObject::connect(&g, SIGNAL(player4_end(std::vector<int>)), &p4,SLOT(post_game_analysis(std::vector<int>)));
QObject::connect(&p4,SIGNAL(turn_complete(bool)), &g, SLOT(turnComplete(bool)));
g.start();
return a.exec();
对话框.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
ui->setupUi(this);
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
ui->graphicsView->setBackgroundBrush(QBrush(QColor(240,240,239)));
diceBG = scene->addRect(0,-150,100,100,QPen(Qt::black,3,Qt::SolidLine,Qt::RoundCap, Qt::RoundJoin),QBrush(Qt::green));
diceRoll = scene->addSimpleText(QString::number(0),QFont("Courier", 72, QFont::Bold, true));
diceRoll->setPos(25,-150);
// Colors
std::vector<std::pair<QColor,QColor> >base_colors
std::make_pair(QColor(92,170,119),QColor(185,219,125)), //G
std::make_pair(QColor(237,235,89),QColor(237,234,138)), //Y
std::make_pair(QColor(92,93,170),QColor(111,111,170)), //B
std::make_pair(QColor(237,57,60),QColor(237,114,125)) //R
;
QBrush white(Qt::white);
QPen blackPen(Qt::black);
blackPen.setWidth(1);
// Cross
scene->addRect(415,-155,160,960,blackPen,QBrush(QColor(195,195,194)));
scene->addRect(15,245,960,160,blackPen,QBrush(QColor(195,195,194)));
scene->addRect(415,245,160,160,QPen(QColor(195,195,194)),QBrush(QColor(195,195,194))); //clean center
// Goal stretch
scene->addRect(50,290,350,70,blackPen,QBrush(base_colors[0].first));
scene->addRect(460,-120,70,350,blackPen,QBrush(base_colors[1].first));
scene->addRect(590,290,350,70,blackPen,QBrush(base_colors[2].first));
scene->addRect(460,420,70,350,blackPen,QBrush(base_colors[3].first));
int x_pos = -10; //start place for green
int y_pos = 220;
int offset = 70;
int small_offset = 50;
int large_offset = 80;
//home fields
home_fields.push_back(QPointF(0,0));
home_fields.push_back(QPointF(630,-170));
home_fields.push_back(QPointF(800,445));
home_fields.push_back(QPointF(190,630));
for(size_t f = 0; f < home_fields.size(); ++f)
addHomeField(home_fields[f].x(),home_fields[f].y(),QBrush(base_colors[f].first));
// Playing fields
std::vector<std::pair<char,char> > directionsstd::make_pair(1,-1),std::make_pair(1,1),std::make_pair(-1,1),std::make_pair(-1,-1) ;
for(size_t d =0; d < directions.size(); ++d)
for(int i=0; i<5;++i)
if(d % 2 == 0)
x_pos += directions[d].first * offset;
else
y_pos += directions[d].second * offset;
fieldPos.push_back(QPointF(x_pos,y_pos));
x_pos += directions[d].first * small_offset;
y_pos += directions[d].second * small_offset;
for(int i=0; i<5;++i)
fieldPos.push_back(QPointF(x_pos,y_pos));
if(d % 2 == 0)
y_pos += directions[d].second * offset;
else
x_pos += directions[d].first * offset;
for(int i=0; i<2;++i)
fieldPos.push_back(QPointF(x_pos,y_pos));
if(d % 2 == 0)
x_pos += directions[d].first * large_offset;
else
y_pos += directions[d].second * large_offset;
fieldPos.push_back(QPointF(x_pos,y_pos));
//goal stretches
for(int x=60; x<=340; x+=offset)
fieldPos.push_back(QPointF(x,300));
for(int y=-110; y<=170; y+=offset)
fieldPos.push_back(QPointF(470,y));
for(int x=880; x>=600; x-=offset)
fieldPos.push_back(QPointF(x,300));
for(int y=710; y>=430; y-=offset)
fieldPos.push_back(QPointF(470,y));
QImage globe_img("../globe.png");//http://www.clker.com/clipart-world-black-and-white.html
QImage star_img("../star.png"); //http://www.clker.com/clipart-2568.html
// QGraphicsPixmapItem globe( QPixmap::fromImage(QImage("../globe.png")));
// QGraphicsPixmapItem star( QPixmap::fromImage(QImage("../star.png")));
for(size_t c = 0; c < base_colors.size(); ++c)
scene->addEllipse(fieldPos[0+13*c].x(),fieldPos[0+13*c].y(),50,50,QPen(base_colors[c].first),QBrush(base_colors[c].second));
for(int i=1; i < 13; ++i)
if(i == 8)
QGraphicsPixmapItem * globe = new QGraphicsPixmapItem( QPixmap::fromImage(globe_img));
globe->setPos(fieldPos[i+13*c]);
globe->setScale(0.5);
scene->addItem(globe);
else if(i == 5 || i == 11)
QGraphicsPixmapItem * star = new QGraphicsPixmapItem( QPixmap::fromImage(star_img));
star->setPos(fieldPos[i+13*c]);
star->setScale(0.5);
scene->addItem(star);
else
scene->addEllipse(fieldPos[i+13*c].x(),fieldPos[i+13*c].y(),50,50,blackPen,white);
for(size_t g = 52; g < fieldPos.size(); ++g)
scene->addEllipse(fieldPos[g].x(),fieldPos[g].y(),50,50,blackPen,white);
create_graphic_players();
std::vector<int> init_pos(16,-1);
update_graphics(init_pos);
void Dialog::update_graphics(std::vector<int> player_positions)
QPointF p;
for(size_t i = 0; i < player_positions.size(); ++i)
if(player_positions[i] == -1)
p = home_fields[i / 4];
if(i % 4 == 0)
graphic_player[i]->setPos(p.x()+65 ,p.y()+15 );
else if(i % 4 == 1)
graphic_player[i]->setPos(p.x()+65 ,p.y()+115);
else if(i % 4 == 2)
graphic_player[i]->setPos(p.x()+15 ,p.y()+65 );
else if(i % 4 == 3)
graphic_player[i]->setPos(p.x()+115,p.y()+65 );
else if(player_positions[i] == 99)
if(i/4 == 0)
if(i % 4 == 0) graphic_player[i]->setPos(405,300); //left
else if(i % 4 == 1) graphic_player[i]->setPos(405,270);
else if(i % 4 == 2) graphic_player[i]->setPos(405,330);
else if(i % 4 == 3) graphic_player[i]->setPos(435,300);
else if(i/4 == 1)
if(i % 4 == 0) graphic_player[i]->setPos(470,235); //up
else if(i % 4 == 1) graphic_player[i]->setPos(440,235);
else if(i % 4 == 2) graphic_player[i]->setPos(500,235);
else if(i % 4 == 3) graphic_player[i]->setPos(470,265);
else if(i/4 == 2)
if(i % 4 == 0) graphic_player[i]->setPos(535,300); //right
else if(i % 4 == 1) graphic_player[i]->setPos(535,270);
else if(i % 4 == 2) graphic_player[i]->setPos(535,330);
else if(i % 4 == 3) graphic_player[i]->setPos(505,300);
else if(i/4 == 3)
if(i % 4 == 0) graphic_player[i]->setPos(470,365); //down
else if(i % 4 == 1) graphic_player[i]->setPos(440,365);
else if(i % 4 == 2) graphic_player[i]->setPos(500,365);
else if(i % 4 == 3) graphic_player[i]->setPos(470,335);
else
graphic_player[i]->setPos(fieldPos[player_positions[i]]);
ui->graphicsView->repaint();
void Dialog::create_graphic_players()
graphic_player.clear();
QBrush piece;
QPen blackPen(Qt::black);
blackPen.setWidth(1);
for(int c = 0; c<4; ++c)
if(c == 0)
piece = QBrush(QColor(Qt::green));
else if(c == 1)
piece = QBrush(QColor(Qt::yellow));
else if(c == 2)
piece = QBrush(QColor(Qt::blue));
else if(c == 3)
piece = QBrush(QColor(Qt::red));
for(int i = 0; i<4; ++i)
graphic_player.push_back(scene->addEllipse(5,5,40,40,blackPen,piece));
Dialog::~Dialog()
delete ui;
void Dialog::showEvent(QShowEvent *)
ui->graphicsView->fitInView(scene->itemsBoundingRect(),Qt::KeepAspectRatio);
void Dialog::resizeEvent(QResizeEvent *)
ui->graphicsView->fitInView(scene->itemsBoundingRect(),Qt::KeepAspectRatio);
void Dialog::get_winner(int color)
scene->addRect(0,500,1000,200,QPen(Qt::black,3,Qt::SolidLine,Qt::RoundCap, Qt::RoundJoin),QBrush(active_color));
QGraphicsSimpleTextItem * win = scene->addSimpleText(QString("Winner is found!"),QFont("Courier", 72, QFont::Bold, true));
win->setPos(50,550);
void Dialog::get_color(int color)
switch(color)
case 0:
active_color = Qt::green;
break;
case 1:
active_color = Qt::yellow;
break;
case 2:
active_color = Qt::blue;
break;
case 3:
active_color = Qt::red;
default:
break;
void Dialog::get_dice_result(int dice)
current_dice_roll = dice;
diceBG->setBrush(active_color);
diceRoll->setText(QString::number(current_dice_roll));
ui->graphicsView->repaint();
void Dialog::addHomeField(int x, int y,QBrush brush)
QBrush whiteBrush(Qt::white);
QPen blackPen(Qt::black);
blackPen.setWidth(1);
scene->addEllipse(x,y,180,180,blackPen,brush);
scene->addEllipse(x+65 ,y+15 ,50,50,blackPen,whiteBrush);
scene->addEllipse(x+65 ,y+115,50,50,blackPen,whiteBrush);
scene->addEllipse(x+15 ,y+65 ,50,50,blackPen,whiteBrush);
scene->addEllipse(x+115,y+65 ,50,50,blackPen,whiteBrush);
游戏.cpp
#include "game.h"
#define DEBUG 0
game::game()
game_delay = 1000;
game_complete = false;
turn_complete = true;
for(int i = 0; i < 16; ++i)
player_positions.push_back(-1);
color = 3;
void game::reset()
game_complete = false;
turn_complete = true;
for(auto i : player_positions)
i = -1;
color = 3;
int game::rel_to_fixed(int relative_piece_index)
return relative_piece_index + color * 4;
int game::isStar(int index)
if(index == 5 ||
index == 18 ||
index == 31 ||
index == 44)
return 6;
else if(index == 11 ||
index == 24 ||
index == 37 ||
index == 50)
return 7;
return 0;
int game::isOccupied(int index) //returns number of people of another color
int number_of_people = 0;
if(index != 99)
for(size_t i = 0; i < player_positions.size(); ++i)
if(i < color*4 || i >= color*4 + 4) //Disregard own players
if(player_positions[i] == index)
++number_of_people;
return number_of_people;
bool game::isGlobe(int index)
if(index < 52) //check only the indexes on the board, not in the home streak
if(index % 13 == 0 || (index - 8) % 13 == 0 || isOccupied(index) > 1) //if more people of the same team stand on the same spot it counts as globe
return true;
return false;
void game::send_them_home(int index)
for(size_t i = 0; i < player_positions.size(); ++i)
if(i < color*4 || i >= color*4 + 4) //this way we don't skip one player position
if(player_positions[i] == index)
player_positions[i] = -1;
void game::move_start(int fixed_piece)
if(dice_result == 6 && player_positions[fixed_piece] < 0)
player_positions[fixed_piece] = color*13; //move me to start
send_them_home(color*13); //send pieces home if they are on our start
int game::next_turn(unsigned int delay = 0)
if(game_complete)
return 0;
switch(color)
case 0:
case 1:
case 2:
++color;
break;
case 3:
default:
color = 0;
break;
global_color = color;
rollDice();
relative.dice = getDiceRoll();
relative.pos = relativePosition();
emit set_color(color);
emit set_dice_result(dice_result);
msleep(delay);
switch(color)
case 0:
emit player1_start(relative);
break;
case 1:
emit player2_start(relative);
break;
case 2:
emit player3_start(relative);
break;
case 3:
emit player4_start(relative);
default:
break;
return 0;
void game::movePiece(int relative_piece)
int fixed_piece = rel_to_fixed(relative_piece); //index of the piece in player_positions
int modifier = color * 13;
int relative_pos = player_positions[fixed_piece];
int target_pos = 0;
if(player_positions[fixed_piece] == -1) //if the selected piece is in the safe house, try to move it to start
move_start(fixed_piece);
else
//convert to relative position
if(relative_pos == 99)
std::cout << "I tought this would be it ";
else if(relative_pos < modifier)
relative_pos = relative_pos + 52 - modifier;
else if( relative_pos > 50)
relative_pos = relative_pos - color * 5 - 1;
else //if(relative >= modifier)
relative_pos = relative_pos - modifier;
if(DEBUG) std::cout << "color: " << color << " pos: " << relative_pos << " + " << dice_result << " = " << relative_pos + dice_result;
//add dice roll
relative_pos += dice_result; //this is relative position of the selected token + the dice number
int jump = isStar(relative_pos); //return 0 | 6 | 7
if(jump)
if(jump + relative_pos == 57)
relative_pos = 56;
else
relative_pos += jump;
//special case checks
if(relative_pos > 56 && relative_pos < 72) // go back
target_pos = 56-(relative_pos-56) + color * 5 + 1; //If the player moves over the goal, it should move backwards
else if(relative_pos == 56 || relative_pos >= 99)
target_pos = 99;
else if(relative_pos > 50) // goal stretch
target_pos = relative_pos + color * 5 + 1;
else
int new_pos = relative_pos + color * 13;
if(new_pos < 52)
target_pos = new_pos;
else //wrap around
target_pos = new_pos - 52; //this is the global position wrap around at the green entry point
//check for game stuff
if(isOccupied(target_pos))
if(isGlobe(target_pos))
target_pos = -1; //send me home
else
send_them_home(target_pos);
if(DEBUG) std::cout << " => " << target_pos << std::endl;
player_positions[fixed_piece] = target_pos;
std::vector<int> new_relative = relativePosition();
switch(color)
case 0:
emit player1_end(new_relative);
break;
case 1:
emit player2_end(new_relative);
break;
case 2:
emit player3_end(new_relative);
break;
case 3:
emit player4_end(new_relative);
default:
break;
emit update_graphics(player_positions);
std::vector<int> game::relativePosition()
std::vector<int> relative_positons;
int modifier = color * 13;
//from start id to end
for(int i = color*4; i < player_positions.size(); ++i)
relative_positons.push_back(player_positions[i]);
//from 0 to start id
for(int i = 0; i < color*4; ++i)
relative_positons.push_back(player_positions[i]);
for(size_t i = 0; i < relative_positons.size(); ++i)
if(relative_positons[i] == 99 || relative_positons[i] == -1)
relative_positons[i] = (relative_positons[i]);
else if(relative_positons[i] < modifier)
relative_positons[i] = (relative_positons[i]+52-modifier);
else if(relative_positons[i] > 50)
relative_positons[i] = (relative_positons[i]-color*5-1);
else if(relative_positons[i] > modifier)
relative_positons[i] = (relative_positons[i]-modifier);
return std::move(relative_positons);
void game::turnComplete(bool win)
game_complete = win;
turn_complete = true;
if(game_complete)
std::cout << "player: " << color << " won" << std::endl;
emit declare_winner(color);
void game::run()
if(DEBUG) std::cout << "color: relative pos => fixed\n";
while(!game_complete)
if(turn_complete)
turn_complete = false;
msleep(game_delay/4);
next_turn(game_delay - game_delay/4);
emit close();
QThread::exit();
ludo_player.cpp
#include "ludo_player.h"
#include <random>
ludo_player::ludo_player()
int ludo_player::make_decision()
if(dice_roll == 6)
for(int i = 0; i < 4; ++i)
if(pos_start_of_turn[i]<0)
return i;
for(int i = 0; i < 4; ++i)
if(pos_start_of_turn[i]>=0 && pos_start_of_turn[i] != 99)
return i;
else
for(int i = 0; i < 4; ++i)
if(pos_start_of_turn[i]>=0 && pos_start_of_turn[i] != 99)
return i;
for(int i = 0; i < 4; ++i) //maybe they are all locked in
if(pos_start_of_turn[i]<0)
return i;
return -1;
void ludo_player::start_turn(positions_and_dice relative)
pos_start_of_turn = relative.pos;
dice_roll = relative.dice;
int decision = make_decision();
emit select_piece(decision);
void ludo_player::post_game_analysis(std::vector<int> relative_pos)
pos_end_of_turn = relative_pos;
bool game_complete = true;
for(int i = 0; i < 4; ++i)
if(pos_end_of_turn[i] < 99)
game_complete = false;
emit turn_complete(game_complete);
ludo_player_random.cpp
#include "ludo_player_random.h"
ludo_player_random::ludo_player_random()
int ludo_player_random::make_decision()
std::vector<int> valid_moves;
if(dice_roll == 6)
for(int i = 0; i < 4; ++i)
if(pos_start_of_turn[i]<0)
valid_moves.push_back(i);
for(int i = 0; i < 4; ++i)
if(pos_start_of_turn[i]>=0 && pos_start_of_turn[i] != 99)
valid_moves.push_back(i);
if(valid_moves.size()==0)
for(int i = 0; i < 4; ++i)
if(pos_start_of_turn[i] != 99)
valid_moves.push_back(i);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> piece(0, valid_moves.size()-1);
int select = piece(gen);
return valid_moves[select];
void ludo_player_random::start_turn(positions_and_dice relative)
pos_start_of_turn = relative.pos;
dice_roll = relative.dice;
int decision = make_decision();
emit select_piece(decision);
void ludo_player_random::post_game_analysis(std::vector<int> relative_pos)
pos_end_of_turn = relative_pos;
bool game_complete = true;
for(int i = 0; i < 4; ++i)
if(pos_end_of_turn[i] < 99)
game_complete = false;
emit turn_complete(game_complete);
player_q_learning.cpp
http://pastebin.com/bjwFDLgj
player_q_learning.h
http://pastebin.com/zUrnvdsL
由于正文字符最多 30000 个字符,我无法添加 .h。我希望 .cpp 可以让您了解 .h 文件是如何构建的..
【问题讨论】:
你能告诉我们你用过calc_input
的地方,还有player_q_learning
的地方吗?
我添加了一个可以下载整个项目的链接
请附上相关代码,不要发布链接。
我不确定什么是相关的,更具体地说,每个部分都是相互关联的。这使得不可能只为您提供某些文件..
请阅读有关构建MVCE 的信息。每天都有很多问题在这里被问到。为了不浪费时间(并使您的问题更吸引您的回答),您应该包含 相关 代码。 @xsquared 准确地确定了我们需要的内容:player_q_learning
头文件、calc_input
的定义以及头文件的任何 include
语句。
【参考方案1】:
您将calc_input
声明为一个信号,因此您不能实现它。是 Qt 提供了它的实现(在 MOC 生成的文件中),这样当它发出时,它会调用已连接到它的插槽。
如果您不打算将其用作信号(在我看来,鉴于您从未connect
或emit
它),请将其声明移到signals:
部分之外,以便它成为“常规”方法。
【讨论】:
以上是关于构建文件夹中的 Qt 创建者多重定义的主要内容,如果未能解决你的问题,请参考以下文章