我有一個父類 Piece 有幾個子類,包括 Queen、Rook 和 Bishop。然而,Queen 可以像 Rook 和 Bishop 一樣移動,所以它在概念上是兩者的融合。我想從 Queen 類中的 Rook 和 Bishop 類中呼叫函式。我曾嘗試讓 Queen 從 Rook 和 Bishop 繼承,而不是從 Piece 繼承,然后它從 Piece 繼承了兩個屬性副本(一個在 Bishop 中,一個在 Rook 中),這意味著我不能參考。
有沒有辦法做到這一點,或者我只需要為 Queen 重寫函式?
編輯:對不起,我認為我的問題很難用文字來理解。由于這是針對大學的,我無法提供可能違反他們的抄襲政策的代碼,但這里是每個班級的頭檔案。
我基本上要呼叫canMoveTo并squaresInBetween從女王主教和魯克的功能,因為主教可以斜走,車可以水平和垂直移動,和王后可以斜走,水平和垂直方向。
件.h
#ifndef PIECE_H
#define PIECE_H
#include <string>
#include <vector>
using namespace std;
class Piece // abstract
{
public:
Piece(string currentPos); // constructor - sets currentposition
virtual bool canMoveTo(string square) = 0; // able to move to that square on an empty board (movement rules)
virtual vector<string> squaresInBetween(string square) = 0; // squares in between current position and square (including square)
virtual ~Piece(); // virtual destructor to call correct destructor for each piece
string getPosition();
protected:
string currentPosition; // board coordinates (e.g. "d4") // change to char [2] later?
private:
friend class Player;
void setPosition(string pos);
};
#endif
車.h
#ifndef ROOK_H
#define ROOK_H
#include "Piece.h"
class Rook : public Piece
{
public:
Rook(string currentPos);
virtual bool canMoveTo(string square);
virtual vector<string> squaresInBetween(string square);
};
#endif
Bishop.h
#ifndef BISHOP_H
#define BISHOP_H
#include "Piece.h"
class Bishop : public Piece
{
public:
Bishop(string currentPos);
virtual bool canMoveTo(string square);
virtual vector<string> squaresInBetween(string square);
};
#endif
皇后樂隊
#ifndef QUEEN_H
#define QUEEN_H
#include "Piece.h"
class Queen : public Piece
{
public:
Queen(string currentPos);
virtual bool canMoveTo(string square);
virtual vector<string> squaresInBetween(string square);
};
#endif
uj5u.com熱心網友回復:
好吧,如果你是死心塌地的一個面向物件的解決方案-即一個解決方案涉及繼承-你可以使用“混合式”型別的課程MovesLikeRook和MovesLikeBishop,然后從相應的類讓魯克和主教繼承和來自都有女王繼承。
但正如其他人所說,您不需要用 OOP 解決每個程式。在這種情況下,如果您不想多次撰寫相同的車移動和主教移動代碼,您可以將該邏輯放在可由 Rook、Bishop 和 Queen 呼叫的自由或靜態函式中。我的意思是,這是一種想法。但是有很多方法可以不重復自己,也不使用復雜的物件層次結構,這在現代編程中通常被視為一件好事。
uj5u.com熱心網友回復:
我曾嘗試讓 Queen 從 Rook 和 Bishop 繼承,而不是從 Piece 繼承,然后它從 Piece 繼承了兩個屬性副本(一個在 Bishop 中,一個在 Rook 中),這意味著我不能參考。
這種情況被稱為鉆石繼承。C 有一種解決“Piece屬性的兩份副本”問題的方法:虛繼承。它看起來像:
class Piece {/*...*/};
class Rook : virtual public Piece {/*...*/};
class Bishop : virtual public Piece {/*...*/};
class Queen : public Rook, public Bishop {/*...*/};
這可能對你有用,這很少是一個好的設計。
uj5u.com熱心網友回復:
這就是我在沒有虛擬 canMoveTo 和/或多重繼承的情況下檢查移動的方式:
#include <vector>
#include <string>
//-------------------------------------------------------------------------------------------------
// A move is described as steps a piece can make
// all moves only have to desribe the move to top-right as one step
// range will describe the range of a piece in one turn.
// moves will be combined with directions to cover all allowed moves in a turn
struct Move
{
Move(const int x, const int y, const int r) :
x_step{ x },
y_step{ y },
range{ r }
{
}
int x_step;
int y_step;
int range;
};
//-------------------------------------------------------------------------------------------------
// struct to contain directions of a move in a turn
struct Direction
{
int x_direction;
int y_direction;
};
//-------------------------------------------------------------------------------------------------
class Piece
{
public:
explicit Piece(const std::string& start_position, std::vector<Move>&& moves) :
m_position{ start_position },
m_moves{ moves }
{
};
// no need to make this virtual a piece will have all the information it needs
// without inheritance
bool can_move_to(const std::string& position)
{
// use vector of allowed moves
for (const auto& direction : m_directions)
{
for (const auto& move : m_moves)
{
for (int range = 0; range < move.range; range)
{
// calculate if piece can reach position using
// the step sizes from the piece, direction and range
std::string calculated_position;
// ... todo calculation here
if (calculated_position == position) return true;
}
}
}
return false;
}
protected:
Piece() = default;
virtual ~Piece() = default;
Piece(const Piece&) = delete;
Piece& operator=(const Piece&) = delete;
Piece(Piece&&) = delete;
private:
std::string m_position;
std::vector<Move> m_moves;
static std::vector<Direction> m_directions;
};
//-------------------------------------------------------------------------------------------------
// all information needed to check all directions in which a piece can move
std::vector<Direction> Piece::m_directions{ {1,1},{-1,1},{1,-1},{-1,-1} };
//-------------------------------------------------------------------------------------------------
class Rook :
public Piece
{
public:
explicit Rook(const std::string& position) :
Piece(position, {{1,0,8}, {0,1,8}}) // a rook can move one horizontal, or one vertical up to a range of 8 (board size)
{
}
};
//-------------------------------------------------------------------------------------------------
class Bishop :
public Piece
{
public:
explicit Bishop(const std::string& position) :
Piece(position, {{1,1,8}}) // a rook can move diagonally,up to a range of 8 (board size)
{
}
};
//-------------------------------------------------------------------------------------------------
class Knight :
public Piece
{
public:
explicit Knight(const std::string& position) :
Piece(position, { {1,2,1}, {2,1,1} }) // a knight can move 1 horizontally and 2 vertically, or 2 horizontally and 1 vertically
{
}
};
//-------------------------------------------------------------------------------------------------
class Queen :
public Piece
{
public:
explicit Queen(const std::string& position) :
Piece(position, { {1,0,8}, {0,1,8}, {1,1,8} }) // a queen can move horizontally, vertically and diagonally up to a range of 8
// IMO the extra complexity of multiple inheritance or looking up this information
// in Rook & Bishop is not worth the extra code.
{
}
};
int main()
{
Queen queen{ "e7" };
auto can_move = queen.can_move_to("a1");
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/323893.html
上一篇:正確使用屬性的方法
