0

I just wanted to ask a quick question.

I have a class called "ChessPiece"

#ifndef CHESSPIECE_H
#define CHESSPIECE_H

#include "Globals.h"

// Abstract class for inheritence
class ChessPiece {
public:
    // Constructor
    ChessPiece(bool isWhite) : m_isWhite(isWhite) {
    }
    // No dynamic allocation
    ~ChessPiece(void) {}

    // pure virtual functions
    virtual CellLocation *listAvailableMoves(void) = 0;
    virtual char getPieceType(void) = 0;
    virtual ChessPiece *clonePiece(void) = 0;

    // ACCESSORS, MUTATORS
    // isWhite member
    bool isWhite(void) const{
        return m_isWhite;
    }

    void setIsWhite(bool isWhite) {
        m_isWhite = isWhite;
    }

protected:
    bool m_isWhite;
};
#endif

and I have a variable like this:

ChessPiece *m_gameBoard[8][8];

I wanted to know how can I define a pointer to this variable? I thought it'd be something like ChessPiece *(*pGameBoard)[8][8] but it's not what I want. Say for example that I want to make call like this *pGameBoard[2][2]->isWhite() (this doesn't work) How can I do this?

Thanks in advance for your answers.

John John
  • 44
  • 7

3 Answers3

0
ChessPiece *m_gameBoard[8][8];

ChessPiece * (*pGameBoard)[8];
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

ChessPiece *(*pGameBoard)[8][8]; does declare a pointer to the type that m_gameBoard is in ChessPiece *m_gameBoard[8][8];. You would use it with, for example:

(*pGameBoard)[2][2]->isWhite()

However, in most situations, it is satisfactory to point to an element of the outermost array instead of the entire array, as with:

ChessPiece *(*pGameBoard)[8];

A pointer to the entire array and a pointer to the first element of the array are effectively the same address. However, because the latter is equivalent to the former with the * operator already applied, you could use it like this:

pGameBoard[2][2]->isWhite()

Note that, with the first declaration, you would assign or initialize it using a pointer to the entire array, as with:

ChessPiece *(*pGameBoard)[8][8] = &m_gameBoard;

while, in the latter declaration, you would assign or initialize it using a pointer to the first element of the array, as with;

ChessPiece *(*pGameBoard)[8][8] = &m_gameBoard[0];

or, equivalently because the unadorned array is automatically converted to a pointer to its first element, with:

ChessPiece *(*pGameBoard)[8][8] = m_gameBoard;
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Yeah your answer explained a lot. Thanks. I should be using the latter one because it'll enable me not to use the dereferencing operator right? Does the dereferencing operator (*asdf) imply a performance cost? – John John Jan 08 '14 at 16:08
  • @JohnJohn: I expect there to be no performance cost because the dereference operation in this circumstance is completely resolvable at compile time with no run-time value change in any normal C++ implementation. (It just changes the type from “pointer to array” to “pointer to element” while still pointing to the same place.) The C++ standard does not **require** that there be no performance cost, but any implementation for a normal modern architecture that does have a performance cost is of very poor quality. Most people use the latter because of its “natural” appearance. – Eric Postpischil Jan 08 '14 at 16:12
0

I'm not sure how you're allocating space for those ChessPiece objects. Whether I try it allocating on the stack or dynamically, I get compilation errors from g++ because there's no default constructor. When you allocate an array of instances on the stack or using new, the default constructor is called for each instance created.

In your ChessPiece class add a default constructor:

ChessPiece() : m_isWhite(false) {}

Then you can allocate the array on the stack as:

ChessPiece pieces[8][8];

And access that array using:

pieces[i][j].isWhite();

This seems more straightforward to me, let me know what you think.

Also, you may want to consider organizing using a Board object, which represents a grid of Cell objects. Each Cell tracks whether it has a piece in it, and if it does, can return a reference/copy of that piece. To me, that's clearer conceptually, but there's nothing wrong with your way, either. :)

Keeler
  • 2,102
  • 14
  • 20
  • Well the point was to use a dynamic array so that it wouldn't imply a cost on the heap size. I've modified the code so that a "ChessPiece" is now only 2 bytes whereas a pointer to it would be 4 bytes. In terms of your approach, we're both using the same thought behind board representation, names doesn't matter. The only other option was not to store a board but an array of pieces that store their own location. However that had some performance costs when searching a location, thus I've chosen this. Thanks for your interest. – John John Jan 10 '14 at 00:18
  • I don't understand what you mean.. Dynamically allocating takes up heap space by definition. At this point, you should focus on getting the program to work correctly. Premature optimization is the root of all evil! I really wouldn't worry about whether its two or 4 bytes, or about the cost on the heap. Unless you're working with a computer that's a few decades old, memory should be more than abundant enough for a chess board. – Keeler Jan 10 '14 at 00:21
  • How much of a performance hit did the piece search result in? You can do a linear search, which on an array of 64 items would take no time. – Keeler Jan 10 '14 at 00:26