如何将派生类型的对象放入用于基本类型的向量中?

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】:

您不会创建任何实际对象。到目前为止,您所有的指针都悬而未决。此外,您还有一整套游戏棋子指针作为成员除了到您的棋盘。

使用&amp;(操作员地址)将它们的地址放入你的板子可能会更好。

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&lt;std::array&lt;ChessPiece*&gt;, 8&gt;, 8&gt; 而不是向量。但这会使您的 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;

【讨论】:

无法分配数组。 对不起,我没听懂。

以上是关于如何将派生类型的对象放入用于基本类型的向量中?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 WCF 将派生类型序列化为其基类型

如何从包含基类指针的容器中调用派生类函数(基于其类型)?

实体框架:如何从 L2E 返回基本类型

在基类类型的向量中保存的基对象和派生对象被切片

在 C++ 中将派生类类型的向量链接到父类类型的向量

如何将对象存储在向量中的对象中? (C++)