Аннотация / Базовая структура в C ++? - PullRequest
5 голосов
/ 27 января 2012

Я играю в шахматы и хотел бы иметь множество фигур.

Если я прав, в Java вы можете иметь абстрактный класс Piece и иметь King или Queen для расширения этого класса.Если бы я создал массив из Piece с, я мог бы поместить King часть где-то в этом массиве и Queen часть в другое место, потому что и King, и Queen расширяются Piece.

Есть ли способ сделать это со структурами в C ++?

Ответы [ 6 ]

6 голосов
/ 27 января 2012

Да. Вы можете создать абстрактный базовый класс в C ++. Просто установите один или несколько методов как чисто виртуальные:

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
};
4 голосов
/ 27 января 2012

Вы можете смоделировать Абстрактный класс в C ++, добавив в класс чисто виртуальную функцию.

В c ++ Вы можете делать все со структурами, которые вы можете на классах.
Структура в C ++ отличается от класса только с точки зрения спецификации доступа по умолчанию для членов и во время наследования.

3 голосов
/ 27 января 2012

Конечно.

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();
1 голос
/ 27 января 2012

Я предпочитаю избегать использования указателей, так как вы должны помнить, чтобы очистить их.

В этом дизайне используется шаблон стратегии.Интерфейс 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);
    //...
}

Боннский шанс!

1 голос
/ 27 января 2012

В 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()
1 голос
/ 27 января 2012

Вы можете использовать наследование в 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(); 
...