我正在做一個國際象棋遊戲,我想有一個片段的數組。C++中的Abstract/Base結構?
如果我沒錯,在Java中可以有一個抽象的Piece
類,並且有King
或Queen
擴展那個類。如果我要製作一排Piece
,我可以在該陣列的某處放置King
片,並在另一個位置放置Queen
片,因爲King
和Queen
都會延伸Piece
。
有什麼辦法可以用C++中的結構來做到這一點嗎?
我正在做一個國際象棋遊戲,我想有一個片段的數組。C++中的Abstract/Base結構?
如果我沒錯,在Java中可以有一個抽象的Piece
類,並且有King
或Queen
擴展那個類。如果我要製作一排Piece
,我可以在該陣列的某處放置King
片,並在另一個位置放置Queen
片,因爲King
和Queen
都會延伸Piece
。
有什麼辦法可以用C++中的結構來做到這一點嗎?
是的。你可以用C++創建一個abstract base class。簡單地設置一個或多個的方法是純虛:
class Piece {
public:
Piece();
virtual ~Piece();
virtual void SomeMethod() = 0; // This method is not implemented in the base class, making it a pure virtual method. Subclasses must implement it
};
然後,您可以創建一個實現純虛方法
class King : public Piece {
// ... the rest of the class definition
virtual void SomeMethod(); // You need to actually implement this
};
通過向類中添加純虛函數,可以在C++中模擬Abstract class。
在C++中,您可以使用可以在類上進行的結構來完成所有任務。
C++中的結構僅在成員的默認訪問規範和繼承期間與類不同。
可以在幾乎相同的使用繼承在C++中的子類就像你在Java中一樣。 C++既有類又有結構,在這種情況下,你可以使用其中一種。
C++中的抽象類只是其中包含純虛方法的類。這些是沒有方法定義的方法。
您的解決方案可能是這個樣子:
class Piece {
public:
virtual ~Piece();
virtual void move() = 0; //this is a pure virtual function, making this an abstract class.
};
class King : public Piece {
public:
void move() {};
};
class Queen : public Piece {
public:
void move() {};
};
....
Piece *myPieces[2] = new Piece*[2];
myPieces[0] = new King();
myPieces[1] = new Queen();
肯定。
class AbstractPiece
{
public:
virtual void aFunction()=0; //this makes AbstractPiece an abstract class.
virtual ~AbstractPiece();
};
class King : public AbstractPiece
{
public:
virtual void aFunction(); //this is the one that would get called
virtual ~King();
};
再後來,
AbstractPiece* array[size];
和
array[index] = new King();
你缺少一個虛擬析構函數。 – 2012-01-27 10:27:54
你說得對。我編輯了我的答案。 – Julius 2012-01-27 18:05:15
在C++中,你可以使用抽象類或結構:
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/construct.hpp>
using namespace std;
struct piece
{
virtual ~piece() {};
virtual void dosomething() = 0;
};
struct king : piece
{
~king() { cout << __PRETTY_FUNCTION__ << endl; }
void dosomething() { cout << __PRETTY_FUNCTION__ << endl; }
};
struct queen : piece
{
~queen() { cout << __PRETTY_FUNCTION__ << endl; }
void dosomething() { cout << __PRETTY_FUNCTION__ << endl; }
};
struct pawn : piece
{
~pawn() { cout << __PRETTY_FUNCTION__ << endl; }
void dosomething() { cout << __PRETTY_FUNCTION__ << endl; }
};
用法:
int main()
{
typedef std::vector< piece * > pieces_t;
pieces_t pieces;
pieces.push_back(new queen());
pieces.push_back(new king());
pieces.push_back(new pawn());
pieces.push_back(new pawn());
pieces.push_back(new pawn());
pieces.push_back(new pawn());
// calling dosomething()
std::for_each(pieces.begin(), pieces.end(),
boost::lambda::bind(&piece::dosomething, boost::lambda::_1));
// destructing
std::for_each(pieces.begin(), pieces.end(),
boost::lambda::bind(boost::lambda::delete_ptr(), boost::lambda::_1));
}
輸出:
virtual void queen::dosomething()
virtual void king::dosomething()
virtual void pawn::dosomething()
virtual void pawn::dosomething()
virtual void pawn::dosomething()
virtual void pawn::dosomething()
virtual queen::~queen()
virtual king::~king()
virtual pawn::~pawn()
virtual pawn::~pawn()
virtual pawn::~pawn()
virtual pawn::~pawn()
對於一個非常簡單的問題,這是一個令人難以置信的複雜答案!你真的需要引入'__PRETTY_FUNCTION__',boost,lambdas,標準算法等嗎? – 2012-01-27 10:27:11
@LucTouraille我習慣於使用'__PRETTY_FUNCTION__',因爲它顯示了類名和參數類型/返回值。通過這種方式很容易看到被調用的內容。至於其他的問題,我真的不想花更多的時間做一個簡單的答案,所以我用了第一個想到的東西 - 當然,我可以花更多的時間打字,並使答案更長... – stefanB 2012-01-28 06:20:52
我寧願避免使用指針,你一定要記住清除它們。
本設計使用策略模式。界面是PieceType
,它允許您顯示板上的有效位置,或顯示板上的初始位置。我敢肯定,還有更多你想每一個戰略,能夠做到:
class Board;
class PieceType
{
public:
virtual showValidMoves(Board& board) const = 0;
virtual showInitialPosition(Board& board) const = 0;
// ...
};
class Pawn : public PieceType
{
public:
virtual showValidMoves(Board& board) const;
virtual showInitialPosition(Board& board) const;
// ...
};
class Rook : public PieceType
{
// ...
};
//...
我們只需要每個PieceType
之一,因爲這種類型的跨棋子共享,也可以是常量:
const Pawn PAWN;
const Rook ROOK;
const Knight KNIGHT;
我們使用這些策略來初始化棋子,我們保持一個向量:
class ChessMan
{
public:
enum Colour {Black, White};
ChessMan(const Colour& colour, PieceType& pieceType);
void showValidMoves(Board& board);
void showInitialPosition(Board& board);
private:
Colour m_colour;
PieceType& m_pieceType;
};
我包裹起來的代碼在自己的功能添加到ChessMan
矢量:
void add(vector<ChessMan>& chessmen,
const ChessMan::Colour& colour,
const PieceType& pieceType,
const unsigned int amount)
{
chessmen.insert(chessmen.end(), ChessMan(colour, pieceType), amount);
}
void main()
{
using std::vector;
vector<ChessMan> chessmen;
add(chessmen, 16, ChessMan::Black, PAWN);
add(chessmen, 2, ChessMan::Black, ROOK);
add(chessmen, 2, ChessMan::Black, KNIGHT);
//...
}
Bonne的機會!
問題是關於抽象基類,而不是關於國際象棋遊戲的最佳設計。儘管你的回答可能會讓你感興趣的原始海報,但它根本沒有解決這個問題。 – 2012-01-27 10:36:02
@LucTouraille我認爲使用容器進行同質數據很重要。異構行爲更好地存儲在別處。所以我把這些指向抽象類的指針放在同類對象中。我認爲這是一個很好的原則。如果這個例子太長了,或者我提供了一個完整的解決方案,我很抱歉。你可以自由編輯它,並使其更好。 – 2012-01-27 10:55:00
結構通常是c,C++給你類和OOP所以我會堅持,因爲你是新來的c/c + +。 – L7ColWinters 2012-01-27 06:06:29
@ L7ColWinters:爲什麼結構不是OOP?爲什麼你應該使用類呢? – 2012-01-27 06:07:43
@ L7ColWinters:這是一個奇怪的聲明。 'struct'和'class'幾乎完全相同。 – EboMike 2012-01-27 06:11:44