C++ 对象共享错误 LNK2005 和 LNK 1169
C++ Object-sharing Errors LNK2005 and LNK 1169
我目前正在尝试创建一个由玩家 class 在玩家共享的棋盘对象上创建的两个玩家对象轮流玩的井字游戏。据我所知,我已经完成了这个程序,但是当我尝试构建时,我遇到了这些错误并且似乎无法找到原因。我对面向对象编程比较陌生。这是我得到的错误:
1>Player.obj : error LNK2005: "public: __thiscall Player::Player(class Board *,char)" (??0Player@@QAE@PAVBoard@@D@Z) already defined in Connect_Four_Game.obj
1>fatal error LNK1169: one or more multiply defined symbols found
代码如下:
#ifndef ___PLAYER_H___
#define ___PLAYER_H___
#include <iostream>
#include "Board.h"
using namespace std;
class Player {
private:
Board * sharedboard;
char player_char;
public:
Player(Board *shared_board, const char player_char);
bool play(int &choice);
bool wins();
bool columnFull(int&choice);
};
Player:: Player(Board *shared_board,const char player_char)
: player_char(player_char), sharedboard(shared_board)
{}
#endif
板头文件:
#ifndef ___BOARD_H___
#define ___BOARD_H___
#include <iostream>
#include <vector>
using namespace std;
class Board {
public:
vector<vector<char>> holder;
void displayBoard();
bool isBoardFull();
Board()
{
vector<vector<char>>holder(7, vector<char>(7, 'A'));
}
};
#endif
播放器 cpp 文件:
#include <iostream>
#include "Player.h"
using namespace std;
bool Player::columnFull(int &choice)//DONE
{
for (int i = 6; i >= 0; i--)
{
if(sharedboard->holder[i][choice]=='A')//if the choice is not full
{
sharedboard->holder[i][choice] = player_char;//put the players character(X or O here)
return false;
}
else//if the choive is full
{
return true;
}
}
}
bool Player::play(int &choice)//DONE
{
if(choice < 0 )
{
cout << "Choice is not valid." << endl;
return false;
}
else if(choice > 6)
{
cout << "Choice is not valid." << endl;
return false;
}
else if(columnFull( choice))//if its true then its full
{
cout << "Choice is not valid." << endl;
return false;
}
else
{
sharedboard->displayBoard();//if previous ones were false, then the place was empty, and filled, therefore the board will be displayed
}
}
bool Player::wins()//if the player wins
{
int o = 0;
int x = 0;
for (int i = 0; i < 7; i++)//HORIZONTAL
{
for (int j = 0; j < 7; j++)
{
if (sharedboard->holder[i][j] == 'O')
{
o++;
}
else if (sharedboard->holder[i][j] == 'X')
{
x++;
}
if (o == 4)//if O is four horizantily
{
cout << "Player2 wins!" << endl;
sharedboard->displayBoard();
return true;
}
else if (x == 4)//if X is four horizantily
{
cout << "Player1 wins!" << endl;
sharedboard->displayBoard();
return true;
}
}
}//HORIZONTAL
o = 0;
x = 0;
for (int i = 0; i < 7; i++)//VERTICALLY
{
for (int j = 0; j < 7; j++)
{
if (sharedboard->holder[j][i] == 'O')
{
o++;
}
else if (sharedboard->holder[j][i] == 'X')
{
x++;
}
if (o == 4)//if O is four vertically
{
cout << "Player2 wins!" << endl;
sharedboard->displayBoard();
return true;
}
else if (x == 4)//if X is four vertically
{
cout << "Player1 wins!" << endl;
sharedboard->displayBoard();
return true;
}
}
}//VERTICALLY
}
电路板 cpp 文件:
#include "Board.h"
#include<iostream>
using namespace std;
void Board::displayBoard()//DONE
{
for (int i = 0; i < 7; i++)
{
for (int j = 0; j < 7; j++)
{
cout << holder[i][j] << " ";
}
cout << endl;
}
}
bool Board::isBoardFull()//DONE-CORRECTED
{
for (int i = 0; i < 7; i++)
{
for (int j = 0; j < 7; j++)
{
if (holder[i][j] == 'A')
{
return false;//game continues
}
else if(((i==6)&&(j==6)))
{
return true;//ends in tie
}
}
cout << endl;
}
}
主要源文件:
#include<iostream>
#include<string>
#include "Board.h"
#include "Player.h"
using namespace std;
int main()
{
Board myBoard = Board();
/*
//Create your player objects based on your choice of approach to share an object.
//The parameters "..." are left for you to set.
Player player1 = Player(...);
Player player2 = Player(...);
*/
Player player1(&myBoard, 'X');
Player player2(&myBoard, 'O');
int col, turn = 0;
bool continueGame = true;
bool validMove = false;
while(continueGame)
{
myBoard.displayBoard();
if(turn == 0)
{
cout << "Player 1 turn: " << endl;
cin >> col;
validMove = player1.play(col);
if(player1.wins())
{
continueGame = false;
cout << "Player1 won the game!" << endl;
}
}
else if(turn == 1)
{
cout << "Player 2 turn: " << endl;
cin >> col;
validMove = player2.play(col);
if(player2.wins())
{
continueGame = false;
cout << "Player2 won the game!" << endl;
}
}
if(continueGame) {
//If a valid move has been done, change the turn
if(validMove) {
turn = (turn + 1) % 2;
}
if(myBoard.isBoardFull())
{
continueGame = false;
cout << "Noone won the game!" << endl;
}
}
}
cout << "Game is over!" << endl;
cout << "Final state of the board: " << endl;
myBoard.displayBoard();
return 0;
}
我没有 post 整个播放器 cpp 文件,因为它大约有 600 行,只有对角线搜索的重复,没有其他内容。现在谢谢你。
错误提示您定义了多个符号。最有可能的是,您在其他一些文件中多次(直接或间接)包含了 Player.cpp 文件(而不是 Player.h)(您没有共享 Connect_Four_Game 文件)。
我建议您做一些研究:如果包含 .cpp 文件会发生什么情况?阅读声明、定义、多重包含……。这也可能有用:
Already defined in .obj - no double inclusions
我一开始和你一样,问了不好的问题(我想每个人都这样)。下次,您应该尝试检测链接器错误发生的位置,并知道什么是链接器错误。
我清楚地记得我开始使用 C++ 的日子。由于您显然在这段代码中付出了努力,请允许我给您一些与您发布的代码相关的建议。
设计
在编码之前,做好设计。可以在玩家之间共享一个棋盘。您还可以拥有玩家订阅的看板。无论哪种方式:
Board 应该了解自己的一切。也就是说:玩家不应该访问棋盘的属性 "holder" 来查看一个方格是否被占用。玩家应该直接问棋盘:那个方格是空的吗?
同理,columnFull不应该是Player的方法。
代码
你应该尝试使用现代 C++。我重写了你的一些代码。
播放器构造函数:使用智能指针
Player(const std::shared_ptr<Board>& board, std::string&& name) :
m_name(std::move(name)), m_board(board)
{}
您的主文件现在看起来像这样:
std::shared_ptr<Board> myBoard = std::make_shared<Board>();
Player me(myBoard,"Me");
Player you(myBoard,"You");
参考built-in类型:
bool play(const int choice) // no reference to built-in types unless needed
尽可能使用常量:
bool wins() const // should be const, you don't want to modify "this"
使用私有成员、字符串而不是字符和智能指针
private:
std::shared_ptr<Board> m_board; // use smart pointers
std::string m_name; // not playerChar -> it's obvious its about the player
看看现代 C++ 多棒:
void display() const // use const if you don't modify this
{
// you had hardcoded numbers here (7)... try to avoid that, keep the code generic
for (const auto& v : m_holder) // you do have access to C++11 I hope?
{
for (const auto& h : v)
std::cout << h << std::endl;
}
}
使用标准库:
bool isFull() const // try to use the wonderful standard library, your code will be much more readable
{
for (const auto& v : m_holder)
{
auto it = std::find_if(v.begin(),v.end(),[](const std::string& h){ return h.empty(); });
if (it==v.end())
return false;
}
return true;
// cout << endl shouldn't be in this function which checks if the board is full...
}
也许一些 typedef 来保持代码干净?此外,使用 _ 或 m_ 作为属性。尽可能将属性保密。
private: // try to keep members in private so you control who changes them
// maybe use typedef? you use that type multiple times
typedef std::vector<std::vector<std::string>> HolderType;
HolderType m_holder; // for members, use _ or m_
总体
- 在编码之前专注于设计。
- 使用现代 C++、标准库、...
- 使用智能指针。
- 了解何时使用常量、引用、...
- 保持代码整洁。
这当然是一个非常不完整的建议列表。但这些是您代码的主要缺陷。
希望对您有所帮助。
我目前正在尝试创建一个由玩家 class 在玩家共享的棋盘对象上创建的两个玩家对象轮流玩的井字游戏。据我所知,我已经完成了这个程序,但是当我尝试构建时,我遇到了这些错误并且似乎无法找到原因。我对面向对象编程比较陌生。这是我得到的错误:
1>Player.obj : error LNK2005: "public: __thiscall Player::Player(class Board *,char)" (??0Player@@QAE@PAVBoard@@D@Z) already defined in Connect_Four_Game.obj
1>fatal error LNK1169: one or more multiply defined symbols found
代码如下:
#ifndef ___PLAYER_H___
#define ___PLAYER_H___
#include <iostream>
#include "Board.h"
using namespace std;
class Player {
private:
Board * sharedboard;
char player_char;
public:
Player(Board *shared_board, const char player_char);
bool play(int &choice);
bool wins();
bool columnFull(int&choice);
};
Player:: Player(Board *shared_board,const char player_char)
: player_char(player_char), sharedboard(shared_board)
{}
#endif
板头文件:
#ifndef ___BOARD_H___
#define ___BOARD_H___
#include <iostream>
#include <vector>
using namespace std;
class Board {
public:
vector<vector<char>> holder;
void displayBoard();
bool isBoardFull();
Board()
{
vector<vector<char>>holder(7, vector<char>(7, 'A'));
}
};
#endif
播放器 cpp 文件:
#include <iostream>
#include "Player.h"
using namespace std;
bool Player::columnFull(int &choice)//DONE
{
for (int i = 6; i >= 0; i--)
{
if(sharedboard->holder[i][choice]=='A')//if the choice is not full
{
sharedboard->holder[i][choice] = player_char;//put the players character(X or O here)
return false;
}
else//if the choive is full
{
return true;
}
}
}
bool Player::play(int &choice)//DONE
{
if(choice < 0 )
{
cout << "Choice is not valid." << endl;
return false;
}
else if(choice > 6)
{
cout << "Choice is not valid." << endl;
return false;
}
else if(columnFull( choice))//if its true then its full
{
cout << "Choice is not valid." << endl;
return false;
}
else
{
sharedboard->displayBoard();//if previous ones were false, then the place was empty, and filled, therefore the board will be displayed
}
}
bool Player::wins()//if the player wins
{
int o = 0;
int x = 0;
for (int i = 0; i < 7; i++)//HORIZONTAL
{
for (int j = 0; j < 7; j++)
{
if (sharedboard->holder[i][j] == 'O')
{
o++;
}
else if (sharedboard->holder[i][j] == 'X')
{
x++;
}
if (o == 4)//if O is four horizantily
{
cout << "Player2 wins!" << endl;
sharedboard->displayBoard();
return true;
}
else if (x == 4)//if X is four horizantily
{
cout << "Player1 wins!" << endl;
sharedboard->displayBoard();
return true;
}
}
}//HORIZONTAL
o = 0;
x = 0;
for (int i = 0; i < 7; i++)//VERTICALLY
{
for (int j = 0; j < 7; j++)
{
if (sharedboard->holder[j][i] == 'O')
{
o++;
}
else if (sharedboard->holder[j][i] == 'X')
{
x++;
}
if (o == 4)//if O is four vertically
{
cout << "Player2 wins!" << endl;
sharedboard->displayBoard();
return true;
}
else if (x == 4)//if X is four vertically
{
cout << "Player1 wins!" << endl;
sharedboard->displayBoard();
return true;
}
}
}//VERTICALLY
}
电路板 cpp 文件:
#include "Board.h"
#include<iostream>
using namespace std;
void Board::displayBoard()//DONE
{
for (int i = 0; i < 7; i++)
{
for (int j = 0; j < 7; j++)
{
cout << holder[i][j] << " ";
}
cout << endl;
}
}
bool Board::isBoardFull()//DONE-CORRECTED
{
for (int i = 0; i < 7; i++)
{
for (int j = 0; j < 7; j++)
{
if (holder[i][j] == 'A')
{
return false;//game continues
}
else if(((i==6)&&(j==6)))
{
return true;//ends in tie
}
}
cout << endl;
}
}
主要源文件:
#include<iostream>
#include<string>
#include "Board.h"
#include "Player.h"
using namespace std;
int main()
{
Board myBoard = Board();
/*
//Create your player objects based on your choice of approach to share an object.
//The parameters "..." are left for you to set.
Player player1 = Player(...);
Player player2 = Player(...);
*/
Player player1(&myBoard, 'X');
Player player2(&myBoard, 'O');
int col, turn = 0;
bool continueGame = true;
bool validMove = false;
while(continueGame)
{
myBoard.displayBoard();
if(turn == 0)
{
cout << "Player 1 turn: " << endl;
cin >> col;
validMove = player1.play(col);
if(player1.wins())
{
continueGame = false;
cout << "Player1 won the game!" << endl;
}
}
else if(turn == 1)
{
cout << "Player 2 turn: " << endl;
cin >> col;
validMove = player2.play(col);
if(player2.wins())
{
continueGame = false;
cout << "Player2 won the game!" << endl;
}
}
if(continueGame) {
//If a valid move has been done, change the turn
if(validMove) {
turn = (turn + 1) % 2;
}
if(myBoard.isBoardFull())
{
continueGame = false;
cout << "Noone won the game!" << endl;
}
}
}
cout << "Game is over!" << endl;
cout << "Final state of the board: " << endl;
myBoard.displayBoard();
return 0;
}
我没有 post 整个播放器 cpp 文件,因为它大约有 600 行,只有对角线搜索的重复,没有其他内容。现在谢谢你。
错误提示您定义了多个符号。最有可能的是,您在其他一些文件中多次(直接或间接)包含了 Player.cpp 文件(而不是 Player.h)(您没有共享 Connect_Four_Game 文件)。
我建议您做一些研究:如果包含 .cpp 文件会发生什么情况?阅读声明、定义、多重包含……。这也可能有用: Already defined in .obj - no double inclusions
我一开始和你一样,问了不好的问题(我想每个人都这样)。下次,您应该尝试检测链接器错误发生的位置,并知道什么是链接器错误。
我清楚地记得我开始使用 C++ 的日子。由于您显然在这段代码中付出了努力,请允许我给您一些与您发布的代码相关的建议。
设计
在编码之前,做好设计。可以在玩家之间共享一个棋盘。您还可以拥有玩家订阅的看板。无论哪种方式:
Board 应该了解自己的一切。也就是说:玩家不应该访问棋盘的属性 "holder" 来查看一个方格是否被占用。玩家应该直接问棋盘:那个方格是空的吗?
同理,columnFull不应该是Player的方法。
代码
你应该尝试使用现代 C++。我重写了你的一些代码。
播放器构造函数:使用智能指针
Player(const std::shared_ptr<Board>& board, std::string&& name) :
m_name(std::move(name)), m_board(board)
{}
您的主文件现在看起来像这样:
std::shared_ptr<Board> myBoard = std::make_shared<Board>();
Player me(myBoard,"Me");
Player you(myBoard,"You");
参考built-in类型:
bool play(const int choice) // no reference to built-in types unless needed
尽可能使用常量:
bool wins() const // should be const, you don't want to modify "this"
使用私有成员、字符串而不是字符和智能指针
private:
std::shared_ptr<Board> m_board; // use smart pointers
std::string m_name; // not playerChar -> it's obvious its about the player
看看现代 C++ 多棒:
void display() const // use const if you don't modify this
{
// you had hardcoded numbers here (7)... try to avoid that, keep the code generic
for (const auto& v : m_holder) // you do have access to C++11 I hope?
{
for (const auto& h : v)
std::cout << h << std::endl;
}
}
使用标准库:
bool isFull() const // try to use the wonderful standard library, your code will be much more readable
{
for (const auto& v : m_holder)
{
auto it = std::find_if(v.begin(),v.end(),[](const std::string& h){ return h.empty(); });
if (it==v.end())
return false;
}
return true;
// cout << endl shouldn't be in this function which checks if the board is full...
}
也许一些 typedef 来保持代码干净?此外,使用 _ 或 m_ 作为属性。尽可能将属性保密。
private: // try to keep members in private so you control who changes them
// maybe use typedef? you use that type multiple times
typedef std::vector<std::vector<std::string>> HolderType;
HolderType m_holder; // for members, use _ or m_
总体
- 在编码之前专注于设计。
- 使用现代 C++、标准库、...
- 使用智能指针。
- 了解何时使用常量、引用、...
- 保持代码整洁。
这当然是一个非常不完整的建议列表。但这些是您代码的主要缺陷。
希望对您有所帮助。