C++:重载多个子类参数的方法

问题描述 投票:0回答:1

我正在下国际象棋,这是练习基本 OOP 的好方法。有一个抽象基类

Piece
以及
King
Rook
Pawn
等子类以及
Board
类。

有没有办法在board类中创建多个重载函数,根据参数的子类执行不同的操作?这就是我的意思,在非常简单的类结构中:

class Piece {};

class King : public Piece {};

class Rook: public Piece {};

class Pawn: public Piece {};

class Board {
public:
  void move_piece(King piece) {
    ;
  }

  void move_piece(Rook piece) {
    ;
  }

  void move_piece(Pawn piece) {
    ;
  }
};

int main() {
  Board game;
  Pawn pawn;
  Piece p = pawn;
  game.move_piece(p);
}

我已经尝试实现这个,但是当我将一个片段传递给这个重载函数时,它被声明为

Piece
,而不是
Rook
Pawn
。这会导致以下错误:

no suitable user-defined conversion from "Piece" to "Pawn" exists

很公平。但我想做的事情有可能实现吗?

c++ inheritance overloading subclass
1个回答
0
投票

如果您知道

Piece
的确切类型,您编写的代码就会起作用。在这种情况下,通过函数的静态多态性就足够了。

问题是

Piece
是多态的(即动态多态),编译器无法自动知道是否调用采用
Rook
Pawn
等的函数。 穷人的解决方案是尝试使用
Piece
向下转型为
dynamic_cast
的每种可能类型,但这违背了多态性的目的。

相反,请考虑移动

Piece
之间的不同之处:

  • 一块棋子可以移动到不同的方格(例如,
    Pawn
    可以向前移动)
  • 移动到一个正方形会产生不同的结果,例如简单地移动、拿走对手的棋子、晋升为皇后、赢得比赛等等

您可以将其实现为抽象虚函数,例如:

enum class MoveType { None, Move, Attack, Promote };
enum class CheckType { None, Check, CheckMate };

struct MoveResult {
    MoveType type;
    CheckType check;
};

class Piece {
    // ...
  public:
    virtual MoveResult move(Square) = 0;
};

class Pawn : public Piece {
    // ...
  public:
    MoveResult move(Square s) final {
        if (/* can't move to square */) {
            return { MoveType::None, CheckType::None };
        }
        if (/* can move forward to the square */) {
            if (/* promotion */) {
                return { MoveType::Promote, CheckType::None };
            }
        }
        // ...
    }
};

所有特定于片段的逻辑现在都包含在

Piece
的每个派生类中,并且
Board
可以实现
move_piece
,而无需了解这些细节:

// important: pass by reference to avoid object slicing
// note: obtain the square from user input before calling this function;
//       alternatively, get it from user input in here
void Board::move_piece(Piece& piece, Square s) {
    MoveResult result = piece.move(s);
    if (result.check == CheckType::CheckMate) {
        // victory
    }
    if (/* other checks */) {
        // ...
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.