I'm trying to create a chess engine, so I made a Board class (only showing the h file because the implementation is pretty straight forward):
class Board {
private:
Piece* board[SIZE][SIZE];
bool turn;
public:
Board();
Piece* getBoard() const;
void printBoard() const;
};
The idea is to make a 2D array filled with different pieces.
Obviously, I made a Piece class as well (a parent class to all other pieces):
class Piece {
protected:
bool color;
int PosX;
int PosY;
public:
Piece(const bool c, const int x, const int y);
~Piece();
virtual int tryMove(int toX, int toY, Board &board) const = 0;
virtual char toChar() const = 0;
}
I made an EmptyPiece class to try and initialize the array, but I just can't figure out how to fill the array with those pieces.
the h file for EmptyPiece:
class EmptyPiece : protected Piece {
public:
EmptyPiece(const bool c, const int x, const int y);
char toChar() const;
int tryMove(int toX, int toY, Board& board) const;
};
and this is how I'm trying to initialize the array:
Board::Board()
{
turn = true;
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
board[i][j] = EmptyPiece(0, i, j);
}
}
}
which results in an error:
E0413 no suitable conversion function from "EmptyPiece" to "Piece *" exists
On the right side of the following statement:
board[i][j] = EmptyPiece(0, i, j);
EmptyPiece(0, i, j) created a temporary object with type EmptyPiece, which is also convertible to type Piece. But the left side requires a variable of type Piece*, i.e. a pointer to a Piece object. In general, you can't assign a variable of type T to another variable of type T*.
You can fix it with the following version:
board[i][j] = new EmptyPiece(0, i, j);
But you need to remember to delete the objects you new'ed.
Related
If I want my own 1D array class I can overwrite operator[] to read/write the elements. Like:
class A1D {
private:
int a[10]; // This is irrelevant - it's just to simplify the example
// The real class doesn't use a int array.
// Here I just use an int array for simplicity
public:
int& operator[] (int x) { // <--- The interesting part...
return a[x];
}
};
int main()
{
A1D a1d;
a1d[5] = 42;
std::cout << a1d[5] << std::endl;
return 0;
}
The above works fine.
But what if I want to do the same for a 2D array class.
class A2D {
private:
int a[10][10]; // This is irrelevant - it's just to simplify the example
public:
int& operator[][] (int x, int y) { // This, of cause, doesn't work
return a[x][y];
}
};
How would I code [][] to access elements in the 2D array class?
EDIT - some clarification as the first answers didn't fully do what I needed
I used int in the example above for simplicity. In the final class I won't use int so I can't return a int* and the rely on (*int)[..] for the second level.
So I'm looking for:
A2D a;
a[3][4] = SomeOtherClass; // Should call function in A2D with arg 3 and 4
SomeOtherClass x = a[3][4]; // Should call function in A2D with arg 3 and 4
You can make a proxy class which will contain a pointer to the corresponding row of the matrix. Unlike the "return the pointer" approach explained in the other answer, this one can be as well applied to 3D and multidimensional matrices.
class RowProxy {
private:
int* row;
public:
explicit RowProxy(int* row) : row(row) {}
int& operator[](int y) {
return row[y];
}
};
class A2D {
private:
int a[10][10]; // This is irrelevant - it's just to simplify the example
public:
RowProxy operator[](int x) {
return RowProxy{a[x]};
}
};
You can return a pointer to an array, for example:
class A2D {
private:
int a[10][10];
public:
int* operator[] (int x) {
return a[x];
}
};
I don't like this solution... I think it's best to have a Row and a Col class and return an object, not a raw pointer.
You can also use operator()() instead of the bracket as an alternative
class A2D {
private:
int a[10][10];
public:
int& operator()(int x, int y) {
return a[x][y];
}
};
A2D arr;
// ...
arr(3, 3) = 5;
I have a class that includes a const 2d array of values, and I want to define this array when I call the constructor. I have been told using const on values that should never be changed is preferred, so I wanted to try it in this case.
class A {
public:
A(const int passedArray[2][2]) : memberArray(passedArray) {}
private:
const int memberArray[2][2];
};
const int passedArray[][2] = {
{0,0},
{0,1}
};
A a(passedArray); // fails with "incompatible types
//in assignment of 'const int (*)[2]' to 'const in[2][2]'
A a(&passedArray); // fails
This also fails with const int passedArray[2][2] = ..., with private: const int** memberArray, etc.
I know I have to use an initializer list because a constructor cannot change values of const. Is this possible at all on C++11?
Comments to your question has some good info.
After that here is the working code:
//g++ 5.4.0
#include <iostream>
class A {
public:
A(int passedArray[2][2])
{
//USE STD COPY TO COPY THE ARRAYS.
std::copy(&passedArray[0][0], &passedArray[0][0]+4,&memberArray[0][0]);
//PRINT VALUES TO TEST
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
std::cout << memberArray[i][j] << std::endl;
}
}
}
private:
int memberArray[2][2];
};
int main()
{
//INITIALIZE YOUR ARRAY
int passedArray[2][2] = {
{0,0},
{0,1}
};
//CREATE OBJECT
A a(passedArray);
}
If your business need is to have a "const multi dimensional array in your class"
you have to do it any one of the below ways.
class A {
public:
A(const int passedArray[2][2])
{
}
private:
const int memberArray[2][2] = {{5,6},{7,8}}; //INITIALIZE HERE
};
OR
class A {
public:
A(const int passedArray[2][2])
{
}
private:
//DECLARE STATIC HERE
static const int memberArray[2][2];
};
//INTIALIZE HERE
const int A::memberArray[2][2] = {{5,6},{7,8}};
I have class NumberArray in NumberArray.h
class NumberArray
{
private:
double *aPtr;
int arraySize;
public:
NumberArray(NumberArray &);
NumberArray(int size, double value);
NumberArray() { if (arraySize > 0) delete[] aPtr; }
void print() const;
void setValue(double value);
};
In my cpp file, NumberArray.cpp I define the constructor
NumberArray(NumberArray &)
by
NumberArray::NumberArray(NumberArray &obj)
{
arraySize = obj.arraySize();
aPtr = new double[arraySize];
for (int index = 0; index < arraySize; index++)
{
aPtr[index] = obj.aPtr[index];
}
}
From all I've learned, this should work. However I'm receiving an error "expression preceeding parenthesis of apparent call must have (pointer-to-) function type.
I thought I already did have a point-to function type...
Can someone help me with where I went wrong?
arraySize = obj.arraySize();
arraySize is a class member. It is not a class method. This should be:
arraySize = obj.arraySize;
I'm having a bit of trouble with templating and composition-style coding. I have an object being created inside the constructor of another with the *this parameter. Sorry, if I'm being unclear. The code is as below:
In the outer.h file:
class outer {
public:
outer(int w, int l);
int getWidth();
int getLength();
private:
inner<outer> test(*this);
int width;
int length;
};
outer::outer(int w, int l) {
width = w;
length = l;
}
int outer::getLength() {
return length;
}
In the inner.h file
template<typename T>
class inner {
public:
inner(T &name);
private:
int top;
int bot;
};
template<typename T>
inner<T>::inner(T &name) {
top = name.getLength() /2;
bot = -name.getLength() / 2;
}
I don't know if this is allowed as I can't find anything online that addresses this. The compiler is having problems with the *this statement in outer.h.
Thanks in advance for your help.
If you're using C++03, you must perform initial assignments in the constructor.
class outer {
public:
outer(int w, int l);
int getWidth();
int getLength();
private:
// Member variables are initialized in the order they are declared here.
int width;
int length;
inner<outer> test;
};
outer::outer(int w, int l)
: width(w)
, length(l)
, test(*this)
{
}
Edit: Kerrek SB also observes that the order of your variables need to be changed. They are initialized in the order you declare them in the class and test needs to be initialized last, so the other variables are initialized.
I've been trying to make an class with an array of objects created dynamically. I overloaded the operator + to add (only this for now) a new object to a group of objects (class to class). THe problem is when I read the data in the array, I get all sorts of big numbers . Here is the code:
#include<iostream.h>
class Figura {
public:
int x, y, poz;
int tip; //1 = punct ; 2 = dreapta; 3 = dreptunghi
Figura() { };
Figura(const Figura&) { };
};
class Grup {
private:
int nr_elemente;
Figura *figuri;
public:
int i;
Grup(int nr_el) {
nr_elemente = nr_el;
figuri = new Figura[nr_elemente];
i = 1;
}
~Grup() {};
Grup(const Grup&) {};
int _nr_elemente() {
return i;
}
void adauga_element(Figura fig) {
if( i <= nr_elemente)
figuri[i++] = fig;
else
cout<<"Grupul a atins numarul maxim de figuri.";
}
void afiseaza_elemente() {
for(int j = 1; j <= i; j++)
cout<<"Figura nr : "<<j<<"tip: "<<figuri[j].tip<<figuri[j].x<<" "<<figuri[j].y<<" "<<figuri[j].poz;
}
friend Grup operator+(const Figura& fig1, const Figura& fig2) {
return fig1.poz + fig2.poz;
};
friend Grup operator+(const Grup& gr1, const Grup& gr2) {};
void operator+(const Figura& fig);
friend Grup operator*(const Grup& fig) {};
};
void Grup::operator+(const Figura& fig) {
Grup::adauga_element(fig);
}
class Punct : public Figura
{
public:
Punct(int poz) {
Punct::tip = 1;
Punct::poz = poz;
}
};
class Segment : public Figura
{
public:
Segment(int poz, int x) {
Segment::tip = 2;
Segment::poz = poz;
Segment::x = x;
}
};
class Dreptunghi : public Figura
{
public:
Dreptunghi(int poz, int x, int y) {
Dreptunghi::tip = 3;
Dreptunghi::poz = poz;
Dreptunghi::x = x;
Dreptunghi::y = y;
}
};
void main(void) {
Grup gr(1);
Punct pct(1);
Segment sgm(3, 5);
gr + pct;
gr + sgm;
//cout<<gr.i;
cout<<sgm.x;
gr.afiseaza_elemente();
}
Array indexes run from 0 to N - 1, when N is the array size. The following code will result in out of bounds array access:
void adauga_element(Figura fig) {
if( i <= nr_elemente)
figuri[i++] = fig;
else
cout<<"Grupul a atins numarul maxim de figuri.";
}
Change to:
if( i < nr_elemente)
Same problem in afiseaza_elemente().
As you have dynamically allocated members a destructor must delete[] the dynamically allocated array and a copy constructor and assignment operator need to be correctly implemented, or declared private to prevent copying. As this is C++, consider using std::vector<Figura> instead of an array.
A more simple example would improve understanding.
In any case, your problem is known as object slicing.
In short, you cannot put a derived object in an array of base objects.
To solve the problem you can change the figuri data member to be an array of pointers to Figura:
Figura ** figuri;
// ...
figuri = new Figura*[nr_elemente];
You're not initializing any members. You should do that in the constructor.
For example:
Punct pct(1);
only initializes the members tip and pos, but x and y will contain garbage values, which you probably end up seeing.
You also shouldn't be using a dynamically allocated array as a member - Figura *figuri; but a std::vector. This would save you also from the undefined behavior you're encountering when adding new figures.
Also, note that your destructors and copy constructors have no implementation, which is a source for bugs.
void adauga_element(Figura fig)
passes the object fig is passed by value, so a copy constructor should be implemented.