如何将派生类型的对象放入用于基本类型的向量中?
Posted
技术标签:
【中文标题】如何将派生类型的对象放入用于基本类型的向量中?【英文标题】:How can I put objects of a derived type in a vector meant for the base type? 【发布时间】:2017-12-21 03:53:20 【问题描述】:我刚刚开始了这个项目,但我一直在思考应该如何实现我的 ChessBoard 类。我想要的是我的std::vector<std::vector<ChessPiece*>>
存储从它派生的类型的对象(特定的棋子)。
查看 ChessBoard 类中std::vector<std::vector<ChessPiece*>> board
的分配。
#include <iostream>
#include <string>
#include <vector>
enum class COLOR
BLACK,
WHITE,
NOTHING
;
class ChessPiece
protected:
COLOR color;
public:
ChessPiece() = default;
ChessPiece(COLOR c) : color c
COLOR get_color() const return color;
friend std::ostream& operator<<(std::ostream& out, const ChessPiece piece)
if (piece.color == COLOR::BLACK)
return out << '-';
if (piece.color == COLOR::WHITE)
return out << '+';
;
class King : public ChessPiece
private:
bool moved;
public:
King() = default;
King(COLOR c) color = c;
void set_moved(bool b) moved = b;
bool has_moved() return moved;
;
class Queen : public ChessPiece
private:
public:
Queen() = default;
Queen(COLOR c) color = c;
;
class Bishop : public ChessPiece
private:
public:
Bishop() = default;
Bishop(COLOR c) color = c;
;
class Knight : public ChessPiece
private:
public:
Knight() = default;
Knight(COLOR c) color = c;
;
class Rook : public ChessPiece
private:
bool moved;
public:
Rook() = default;
Rook(COLOR c) color = c;
void set_moved(bool b) moved = b;
bool has_moved() return moved;
;
class Pawn : public ChessPiece
private:
public:
Pawn() = default;
Pawn(COLOR c) color = c;
;
class Board
private:
std::vector<std::vector<ChessPiece*>> board[8][8];
Pawn white_pawn1(COLOR::WHITE), white_pawn2, white_pawn3, white_pawn4, white_pawn5, white_pawn6, white_pawn7, white_pawn8;
Rook white_rook1, white_rook2;
Knight white_knight1, white_knight2;
Bishop white_bishop1, white_bishop2;
Queen white_queen;
King white_king;
Pawn black_pawn1, black_pawn2, black_pawn3, black_pawn4, black_pawn5, black_pawn6, black_pawn7, black_pawn8;
Rook black_rook1, black_rook2;
Knight black_knight1, black_knight2;
Bishop black_bishop1, black_bishop2;
Queen black_queen;
King black_king;
public:
Board(std::string color)
if (color == "white")
**board =
&black_rook1, &black_knight1, &black_bishop1, &black_queen, &black_king, &black_bishop2, &black_knight2, &black_rook2 ,
&black_pawn1, &black_pawn2, &black_pawn3, &black_pawn4, &black_pawn5, &black_pawn6, &black_pawn7, &black_pawn8 ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
&white_pawn1, &white_pawn2, &white_pawn3, &white_pawn4, &white_pawn5, &white_pawn6, &white_pawn7, &white_pawn8 ,
&white_rook1, &white_knight1, &white_bishop1, &white_queen, &white_king, &white_bishop2, &white_knight2, &white_rook2
;
if (color == "black")
**board =
&white_rook1, &white_knight1, &white_bishop1, &white_queen, &white_king, &white_bishop2, &white_knight2, &white_rook2 ,
&white_pawn1, &white_pawn2, &white_pawn3, &white_pawn4, &white_pawn5, &white_pawn6, &white_pawn7, &white_pawn8 ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
&black_pawn1, &black_pawn2, &black_pawn3, &black_pawn4, &black_pawn5, &black_pawn6, &black_pawn7, &black_pawn8 ,
&black_rook1, &black_knight1, &black_bishop1, &black_queen, &black_king, &black_bishop2, &black_knight2, &black_rook2
;
void print_board()
std::cout << "\ta\tb\tc\td\te\tf\tg\th\n1\t";
for (int i = 0; i != 8; ++i)
for (int j = 0; j != 8; ++j)
if (board[i][j] == nullptr)
std::cout << '#' << std::endl;
std::cout << board[i][j] << '\t';
std::cout << std::endl;
if (i != 7)
std::cout << i + 2 << '\t';
~Board() = default;
;
class Game
private:
bool won;
bool lost;
public:
bool is_over();
void update(std::string);
;
int main()
std::cout << "white or black:\n";
std::string color;
std::cin >> color;
// Start game with your given color on the bottom.
// TODO throw exception if user enters an invalid color.
Game game(color);
std::string move;
while (!game.is_over())
std::cin >> move;
game.update(move);
system("pause");
return 0;
【问题讨论】:
您的问题到底是什么?你遇到了什么错误? “查看 ChessBoard 类中 std::vector<:vector>> 棋盘的分配”——究竟有什么值得一看的地方? 我可以看到代码。您是否收到编译器错误?运行时错误?你还没有说你遇到的实际错误是什么。 我认为与其派生相比,最好有一个通用的棋子类并添加其他方面作为组件或装饰器,或者只是维护一种用于应用算法的种类和使用策略。这样会更灵活。 @Shubham 感谢您的意见。我想我可以将每一件作品作为一个单独的类来完成这项工作。一直以来,这只是使用指针的几个愚蠢错误。 【参考方案1】:Rook* white_rook1, white_rook2;
不等于
Rook* white_rook1;
Rook* white_rook2;
但是
Rook* white_rook1;
Rook white_rook2; // not a pointer !!!
(对于所有其他类似的行都相同) 这就是运算符 = 无法匹配的原因。
你也不必在这里使用std::vector
:你的棋盘在游戏过程中不会变大或变小(除非你有特殊的规则:))。请改用std::array
。
您应该注意,您的代码中没有一个指针被初始化。正如Galik 所建议的那样,最好使用对象并将其地址存储在board
中。
【讨论】:
或使用vector
保留大小
感谢您的意见。一直以来,这只是一些使用指针的愚蠢错误。【参考方案2】:
您不会创建任何实际对象。到目前为止,您所有的指针都悬而未决。此外,您还有一整套游戏棋子指针作为成员除了到您的棋盘。
使用&
(操作员地址)将它们的地址放入你的板子可能会更好。
class Board
private:
std::vector<std::vector<ChessPiece*>> board;
// make these non-pointers (many of them already were)
// and give their address to the board
Pawn white_pawn1, white_pawn2, white_pawn3, white_pawn4, white_pawn5, white_pawn6, white_pawn7, white_pawn8;
Rook white_rook1, white_rook2;
Knight white_knight1, white_knight2;
Bishop white_bishop1, white_bishop2;
Queen white_queen;
King white_king;
Pawn black_pawn1, black_pawn2, black_pawn3, black_pawn4, black_pawn5, black_pawn6, black_pawn7, black_pawn8;
Rook black_rook1, black_rook2;
Knight black_knight1, black_knight2;
Bishop black_bishop1, black_bishop2;
Queen black_queen;
King black_king;
public:
Board(std::string color)
if (color == "white")
board =
// NOTE the use of & to take their address aand obtain a pointer
&black_rook1, &black_knight1, &black_bishop1, &black_queen, &black_king, &black_bishop2, &black_knight2, &black_rook2 ,
&black_pawn1, &black_pawn2, &black_pawn3, &black_pawn4, &black_pawn5, &black_pawn6, &black_pawn7, &black_pawn8 ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
&white_pawn1, &white_pawn2, &white_pawn3, &white_pawn4, &white_pawn5, &white_pawn6, &white_pawn7, &white_pawn8 ,
&white_rook1, &white_knight1, &white_bishop1, &white_queen, &white_king, &white_bishop2, &white_knight2, &white_rook2
;
通过使棋子成为适当的对象,它们可以保持单独的状态,而您不必担心创建和销毁它们 - 只需将它们在棋盘上移动(或移入或移出)即可。
另外我会考虑使用std::array<std::array<ChessPiece*>, 8>, 8>
而不是向量。但这会使您的 Board
对象变大。
【讨论】:
感谢您的意见。一直以来,这只是一些使用指针的愚蠢错误。【参考方案3】:我认为你在这里使用向量没有得到任何东西,你可以使用二维数组。喜欢:
#include <iostream>
#include <string>
#include <vector>
class EmptySquare : public ChessPiece
private:
public:
;
class King : public ChessPiece
private:
public:
;
class Queen : public ChessPiece
private:
public:
;
class Bishop : public ChessPiece
private:
public:
;
class Knight : public ChessPiece
private:
public:
;
class Rook : public ChessPiece
private:
public:
;
class Pawn : public ChessPiece
private:
public:
;
enum class COLOR
BLACK,
WHITE,
NOTHING
;
class ChessPiece
private:
COLOR color;
public:
COLOR get_color();
;
class Board
private:
ChessPiece* board[8][8];
Pawn white_pawn1(COLOR(WHITE)), white_pawn2, white_pawn3, white_pawn4, white_pawn5, white_pawn6, white_pawn7, white_pawn8;
Rook white_rook1, white_rook2;
Knight white_knight1, white_knight2;
Bishop white_bishop1, white_bishop2;
Queen white_queen;
King white_king;
Pawn black_pawn1, black_pawn2, black_pawn3, black_pawn4, black_pawn5, black_pawn6, black_pawn7, black_pawn8;
Rook black_rook1, black_rook2;
Knight black_knight1, black_knight2;
Bishop black_bishop1, black_bishop2;
Queen black_queen;
King black_king;
public:
Board(std::string color)
if (color == "white")
ChessPiece* l_board[8][8] =
&black_rook1, &black_knight1, &black_bishop1, &black_queen, &black_king, &black_bishop2, &black_knight2, &black_rook2 ,
&black_pawn1, &black_pawn2, &black_pawn3, &black_pawn4, &black_pawn5, &black_pawn6, &black_pawn7, &black_pawn8 ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
&white_pawn1, &white_pawn2, &white_pawn3, &white_pawn4, &white_pawn5, &white_pawn6, &white_pawn7, &white_pawn8 ,
&white_rook1, &white_knight1, &white_bishop1, &white_queen, &white_king, &white_bishop2, &white_knight2, &white_rook2
;
memcpy(board, l_board, sizeof(ChessPiece*) *8 *8);
if (color == "black")
ChessPiece* l_board[8][8] =
&white_rook1, &white_knight1, &white_bishop1, &white_queen, &white_king, &white_bishop2, &white_knight2, &white_rook2 ,
&white_pawn1, &white_pawn2, &white_pawn3, &white_pawn4, &white_pawn5, &white_pawn6, &white_pawn7, &white_pawn8 ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ,
&black_pawn1, &black_pawn2, &black_pawn3, &black_pawn4, &black_pawn5, &black_pawn6, &black_pawn7, &black_pawn8 ,
&black_rook1, &black_knight1, &black_bishop1, &black_queen, &black_king, &black_bishop2, &black_knight2, &black_rook2
;
memcpy(board, l_board, sizeof(ChessPiece*) *8 *8);
void print_board();
~Board();
;
class Game
private:
bool won;
bool lost;
public:
bool is_over();
void update(std::string);
;
int main()
std::cout << "white or black:\n";
std::string color;
std::cin >> color;
// Start game with your given color on the bottom.
// TODO throw exception if user enters an invalid color.
Game game(color);
std::string move;
while (!game.is_over())
std::cin >> move;
game.update(move);
system("pause");
return 0;
【讨论】:
无法分配数组。 对不起,我没听懂。以上是关于如何将派生类型的对象放入用于基本类型的向量中?的主要内容,如果未能解决你的问题,请参考以下文章