how can I create with Polymorphy 2D-Array of abstract class? - c++

I want to have a 2D array of pointers that contains abstract classes called Piece. So I made a pointer to a 2D array of Piece in a class called Board that have private field of board -Piece** _board.
I tried to use vector or wrap the board field with class but apperently something went wrong..
class Piece
{
public:
Piece(bool, string);
Piece(){};
bool isChass(bool, Board*);
virtual int move(int x_src, int y_src, int x_dst, int y_dst, Board* board)=0;
virtual ~Piece();
bool get_isWhite();
string get_type();
Piece(Piece & other);
Piece& operator= (const Piece & other);
bool inRange(int, int);
protected:
bool _isWhite;
string _type;
};
class Board
{
public:
Board();
Board(const Board& other);
~Board();
Board& operator=(const Board &other);
Piece& getPiece(int i, int j){ return _board[i][j]; }
void game();
void deletePiece(int x, int y) { delete &_board[x][y]; }
void allocateBlankPiece(int x, int y) { _board[x][y] = *new Blank(); }
private:
Piece** _board;
bool _isWhiteTurn;
friend class Piece;
friend class Rock;
friend class Bishop;
friend class Queen;
friend class Knight;
friend class King;
friend class Pawn;
};

You can't use polymorphism for arrays.
An array contains contiguous elements of the same size. But polymorphic elements could be of different size, so that the compiler would not be able to generate code to properly indexing the elements.
You can eventually consider an array of pointers to polymorphic elements:
Piece*** _board; // store pointers to polyorphic elements
But it would be more practical and safer to use vectors:
vector<vector<Piece*>> _board; // Vector of vector of poitners to polymorphic elements
You could also consider even safer smart pointers:
vector<vector<shared_ptr<Piece>>> _board; // assuming that several boards or cells could share the same Piece.

Related

abstract base class problem when iterating through vector of pointers to objects

Hello i am having a specific conceptual problem with abstract base classes i will demonstrate my question in an example with chess classes. I define an abstract base class piece and three other classes pawn bishop and pawn i write these in the following way.
class piece{
public:
wchar_t type;
wchar_t get_piece_symbol() const {return type;}
virtual bool legit_move(int displacement)=0;
virtual ~piece(){}
};
class pawn: public piece{
public:
wchar_t type;
bool move_is_legit(int displacement){....}
wchar_t get_piece_symbol() const {return type;}
.....
};
class knight:public piece{
public:
bool move_is_legit(int displacement){....}
wchar_t get_piece_symbol() const {return type;}
....
};
class bishop:public piece{
public:
bool move_is_legit(int displacement){....}
wchar_t get_piece_symbol() const {return type;}
....
};
The legit_move function makes the piece class abstract.However let's say i want to do the following in the main
std::vector<piece*> Board(64);
piece* a{};
for(int i{0}; i<64; i++){
Board[i] = a;
}
knight *knight_1 = knight{....};
bishop *bishop_1 = bishop{....};
....
Board.at(4)= knight_1
Board.at(4)= bishop_1
....
Essentially what i try to do is create a vector called board containing pointers to pieces. First i fill the Board with pointers to the abstract base class piece(dont know if this makes sense actually) and then i start filling positions of the board with pointers to knight bishop objects etc. So i want to do the following
for(Board_iterator=Board_begin;
Board_iterator<Board_end;++Board_iterator){
std::cout<< (*Board_iterator) -> get_piece_type();
}
}
Essentially for each piece on the board i want to get its symbol when iterating through the vector, but if the Board iterator points to a piece object (abstract base class) the terminal just stops there, is there a way to go about this, so in cases where the Board_iterator corresponds to a piece class pointer can i make some kind of condition to know when this is happening?

Correct way to declare an Array member in a class

I have a class that looks like this
class StatisticsQuantiles : public StatisticsMC
{
public:
StatisticsQuantiles(double p_, unsigned long NumberOfPaths);
virtual void DumpOneResult(double result);
virtual std::vector<std::vector<double>> GetResultsSoFar() const;
virtual StatisticsMC* clone() const;
private:
std::vector<double> ResultList;
double p;
unsigned long PathsDone;
};
Currently it has a vector ResultList which I populate with values in my class when a function is called with a value like so:
void StatisticsQuantiles::DumpOneResult(double result)
{
ResultList.push_back(result);
PathsDone++;
}
Now I know that I will fill this vector with exactly NumberOfPaths many values, so I would like to use an array of a fixed size instead. How do I go about getting an array as a member of this class with size NumberOfPaths? I'm trying to do something like this which doesn't work of course but you get the idea:
class StatisticsQuantiles : public StatisticsMC
{
public:
StatisticsQuantiles(double p_, const unsigned long NumberOfPaths);
virtual void DumpOneResult(double result);
virtual std::vector<std::vector<double>> GetResultsSoFar() const;
virtual StatisticsMC* clone() const;
private:
std::array<double, NumberOfPaths> ResultList;
double p;
unsigned long PathsDone;
};
the size of std::array must be known at compile time, which is not the case here.
So std::vector is your option I believe.
If you are worried about the efficiency of push_back re-sizing, you can reserve the memory in your constructor.
ResultList.reserve(NumberOfPaths);
push_back then won't re-size unless you insert more than NumberOfPaths elements. So you don't have the un-necessary resizing.

How to swap 2 different objects of an object array in C++?

I'm trying to write a Swap function to swap 2 different types of objects of an array in C++. How can I do that? (I prefer using pointer to solve this problem)
I've tried to use template classes to swap 2 objects because the types of object are different from others and when looping through the array, I don't know which objects that one element belongs to.
I have 3 classes (Object_A, Object_B and Object_C) as below:
class Object_A : public base_class
{
private:
int workingTime;
int relaxTime;
float salary;
public:
Object_A();
virtual ~Object_A();
float Cal_Salary();
int getWorkingTime() const;
void setWorkingTime(int workingTime);
int getRelaxTime() const;
void setRelaxTime(int relaxTime);
float getSalary() const;
void setSalary(float salary);
};
class Object_B : public base_class
{
private:
float income;
public:
Officer();
virtual ~Officer();
float getIncome() const;
void setIncome(float income);
};
class Object_C : public base_class
{
private:
std::string role;
float roleCoef;
float bonus;
public:
Manager();
virtual ~Manager();
float Cal_Bonus();
const std::string& getRole() const;
void setRole(const std::string& role);
float getRoleCoef() const;
void setRoleCoef(float roleCoef);
float getBonus() const;
void setBonus(float bonus);
};
// I tried to write SwapValues func
template<class T, class U>
void SwapValues(T* a, U* b)
{
T temp = a;
a = b;
b = temp;
}
I have an array with base_class type to store some elements of three objects above (Object_A, Object_B and Object_C).
However when I want to swap one element of Object_A to one of Object_C with SwapValues() func, it doesn't work!
Thanks a lot for your help.
EDIT: Re-reading your question, the reason why your pointerswap doesn't work is because you are not passing the pointers as reference. If you insist on calling the function SwapValues, you can implement it like this:
class base_class {
// ...
friend void SwapValues(base_class*& a, base_class*& b) {
::std::swap(a,b);
}
};
Observe that SwapValues is still free function, not a member function.
You should always use ::std::swap as it sometimes offers efficient alternatives:
::std::swap(*a,*b);
You can also implement a member function in your class if you want to customise how swap works. For instance, your members can be swapped efficiently, as they are either POD or ::std::string which has a constant-time swap.
I think you should try
void SwapValues(T* a, U* b)
{
T* temp = a;
a = b;
b = temp;
}
Since your array consists of pointers (base_class* elements), you don't need your own swap function. You can just assign such pointers normally, and thus you can just use std::swap.

How to pass a unique_ptr to set the member variable of my object?

I'm writing a chess application. The Board class contains an array of Square, each of which can hold a Piece. Type-specific classes (Pawn, Rook, etc.) inherit from Piece.
In order to accomplish this, Square has a member variable which points to a particular Piece (which is occupying that Square).
The trouble I'm having is that when I try to set up the Board, I am unable to assign the unique_ptr that I've created to the member variable of the Square.
Here's the general stream of function calls:
void Board::setBoard()
{
// White Pawn Placement
std::unique_ptr<Piece> wp1 = std::make_unique<Pawn>(PAWN, WHITE);
Board::setPiece("a2", wp1);
}
↓
Pawn::Pawn(Type t, Color c) : Piece(t, c) {}
↓
void Board::setPiece(const std::string &coords, std::unique_ptr<Piece> piece)
{
squareMap[coords].setPiece(piece);
}
↓
void Square::setPiece(std::unique_ptr<Piece> piece)
{
Square::piece = std::move(piece);
}
I receive the following error when I attempt to compile at the line holding Board::setPiece("a2", wp1);
error: call to implicitly-deleted copy constructor of 'std::unique_ptr<Piece>'
which is, needless to say, a bit of a mouthful.
There is some good documentation online about inheritance, abstract classes, how to use the unique_ptr, etc., but I've been unable to figure out how all of those things fit together.
So, the question:
How can I create an object, assign it to a unique_ptr, and then use that unique_ptr to set the member variable of another object?
Here are the header files for each class, in case that is illuminating. And please forgive the length of my question. I've made it as short as I can.
Board.hpp
class Board {
public:
Board();
void printBoard();
Piece getPiece(const std::string &coords);
void setPiece(const std::string &coords, std::unique_ptr<Piece> piece);
~Board();
...
};
Square.hpp
class Square
{
public:
void setPiece(std::unique_ptr<Piece> piece);
Piece* getPiece() const;
protected:
std::unique_ptr<Piece> piece;
...
};
Piece.hpp
class Piece
{
public:
Piece();
Piece(Type, Color);
virtual bool movePiece() = 0; // abstract class
protected:
Color color;
Type type;
bool moved;
...
};
Pawn.hpp
class Pawn : public Piece
{
public:
Pawn(Type t, Color c);
bool movePiece() override;
};
The problem is you are passing around std::unique_ptr objects by value without the use of std::move(), so you are trying to copy them instead of move them. std::unique_ptr cannot be copied from, only moved from, otherwise single-ownership semantics would be broken. That is what makes std::unique_ptr "unique" - only 1 std::unique_ptr at a time can refer to a given object in memory.
Try something more like this instead:
class Pawn : public Piece
{
public:
Pawn(Color c);
...
};
Pawn::Pawn(Color c) : Piece(PAWN, c) {}
class Square
{
public:
...
// for accessing the current Piece without moving it around the Board
// (for printing, drawing, etc)...
const Piece* getPiece() const;
// for moving Pieces around the Board...
std::unique_ptr<Piece> setPiece(std::unique_ptr<Piece> piece);
...
protected:
std::unique_ptr<Piece> piece;
...
};
const Piece* Square::getPiece() const
{
return piece.get();
}
std::unique_ptr<Piece> Square::setPiece(std::unique_ptr<Piece> piece)
{
std::unique_ptr<Piece> old = std::move(this->piece);
this->piece = std::move(piece);
return std::move(old);
}
class Board {
public:
...
// for accessing a current Piece without moving it around the Board
// (for printing, drawing, etc)...
const Piece* getPiece(const std::string &coords) const;
// for moving Pieces around the Board...
std::unique_ptr<Piece> setPiece(const std::string &coords, std::unique_ptr<Piece> piece);
...
protected:
std::map<std::string, Square> squareMap;
...
};
void Board::setBoard()
{
...
// White Pawn Placement
std::unique_ptr<Piece> wp1 = std::make_unique<Pawn>(WHITE);
setPiece("a2", std::move(wp1));
// or simply:
//setPiece("a2", std::make_unique<Pawn>(WHITE));
...
}
const Piece* Board::getPiece(const std::string &coords) const
{
auto iter = squareMap.find(coords);
return (iter != squareMap.end())
? iter->second.getPiece()
: nullptr;
}
std::unique_ptr<Piece> Board::setPiece(const std::string &coords, std::unique_ptr<Piece> piece)
{
return squareMap[coords].setPiece(std::move(piece));
}
This allows Square to maintain ownership of whatever Piece is currently assigned to it, and that ownership is transferred only when a new Piece is assigned (for instance, to move a captured Piece to another list, to be reclaimed when a Pawn gets promoted).

C++ - How to implement an iterator for a doubly linked list

I have to make a project for college. I have to implement a doubly linked list on an array in C++. The thing is that I'm not allowed to use STL/templates. I implemented the DLL and I'll leave here a code sample:
class DLLA {
private:
int* elements;
int* next;
int* prev;
int size;
int capacity;
// some other variables here if needed
public:
DLLA();
~DLAA();
int getSize();
void addFirst(int x);
void addLast(int x);
void addAtPosition(int x, int position);
// and some other operations and functions
private:
void resize();
};
The problem is that I have to also implement an iterator and I don't really know how. I tried with nested classes but I don't know how to access the DLLA's data members from the iterator and how to generally implement it. Something like this...
class DLLA {
public:
// data members
private:
// functions
public:
class iterator {
private:
int current; // the current position in the vector
public:
void next();
void prev();
// and some other functions
};
};
And also, having nested classes, is it possible to have a function getIterator() in the interface of DLLA which returns the iterator for DLLA?