C++ pointer to 2D array - c++

Hi I know there are a lot of similar questions but I've been through them and I can't seem to make my function work. I need to return a pointer to a 2D array. So far I am using this code:
(This code is a function in Level.cpp)
TileType* CLevel::getTiles()
{
TileType (*matrix_ptr)[31] = tiles;
return *matrix_ptr;
}
(TileType is an enum) This function is just returning one row and I obviously need both. Any suggestions?
Header file Level.h:
class CLevel
{
private:
list<CBox> boxes;
TileType tiles[GRID_HEIGHT][GRID_WIDTH];
CPlayer player;
public:
CLevel();
~CLevel();
CPlayer* getPlayer();
list<CBox>* getBoxes();
TileType** getTiles();
};

Don't define getTiles().
You are completely breaking the encapsulation of the class. This doesn't always matter but in this case the C/C++ 2D array is not a fit structure for passing outside where its dimensions might not be known.
So define your operations on tiles as methods of CLevel.

What you should do is either this:
// Class declaration
class CLevel
{
public:
TileType (*getTiles())[GRID_WIDTH];
TileType tiles[GRID_HEIGHT][GRID_WIDTH];
//...
};
// Implementation
TileType (*CLevel::getTiles())[GRID_WIDTH]
{
return tiles;
}
or this:
// Class declaration
class CLevel
{
public:
TileType (&getTiles())[GRID_WIDTH][GRID_HEIGHT];
TileType tiles[GRID_HEIGHT][GRID_WIDTH];
//...
};
// Implementation
TileType (&CLevel::getTiles())[GRID_WIDTH][GRID_HEIGHT]
{
return tiles;
}
It's a bit of a complicated declaration but read it inside out: in both cases getTiles() is a function that returns a reference to a 2D array of tiles (the example shows two forms of syntax). By calling getTiles() you're actually referring to tiles. You can even call the function it in this way: getTiles()[i][j].

If you want to return a pointer to a 2d array, then your function declaration should be:
TileType** CLevel::getTiles()
And your return should be matrix_ptr, not its pointer content (which is a one-dimension array).
return matrix_ptr;

Related

Returning 2d array of pointers in c++

I have a class and another class with class member of 2d array from the first class type.
and I need a function that returns that class member.
class Piece
{
// something is implemented here/
};
class Board
{
private:
Piece* _pieces[8][8];
public:
Piece*** getPieces()
{
return _pieces;
}
}
but that's not working.
This is a quick version of your class I made to allow the passing of the 2d array to work.
class Board
{
private:
Piece ** _pieces = new Piece*[8];
public:
Board()
{
for(int i = 0; i<8; i++)
_pieces[i] = new Piece[8];
}
Piece** getPieces()
{
return _pieces;
}
~Board()
{
for(int i = 0; i<8; i++) delete [] _pieces[i];
delete [] _pieces;
}
};
You could std::array to create 2D array of pointers if you have access to C++11/14/17, it's a lot cleaner and expressive than using the build in array that decay to a ptr.
What follows is an example of how you create and return from Booard a 8x8 2D array of pointers to Pieces.
#include <array>
class Piece
{
// something is implemented here/
};
using Pieces=std::array<std::array<Piece*,8>,8>;
class Board
{
private:
Pieces _pieces;
public:
const Pieces& getPieces()
{
return _pieces;
}
};
As suggested by #Galik in comment, you should use std::arrays here, because the sizes are constant expressions.
It is not really mandated by the standard, but for common implementations, a std::array<std::array<T,i>,j> does have a true T[i][j] 2D array as underlying data - said differently, consecutive rows use adjacent memory. std::vector on another hand acts more as an array of pointers and data of consecutive rows are generally not adjacent in memory.
Code could become:
class Board
{
private:
std::array<std::array<Piece*, 8>, 8> _pieces;
public:
std::array<std::array<Piece*, 8>, 8>& getPieces()
{
return _pieces;
}
}
But this is still poor design, because it unnecessarily exposes the underlying implementation, so you really should think twice on what should be the public methods for the Board class.
for example,
int a[3][6];
int **p=a; // it's wrong
You should use pointer like this:
int (*p)[6];
p=a;

Inheriting from std:: vector

I am currently creating a class that has to be derived from std:: vector. I realize its probably bad to do this but I'm required to. Now my question is how do you access the created vector in the member functions to basically make the class access itself like a regular vector of integers? For example I am looking for the equivalent of myVector.at(0) to return the first term in the vector. Also, the size of the vector should always be 6. Here is the code I have so far:
class aHistogram : public vector<int>
{
public:
aHistogram(); //default constructor for histogram class
void update(int face); //Function to update histogram
void display(int maxLengthOfLine); //Displays histogram to the scale of maxLengthOfLine using x's
void clear();//Function to clear histogram bin counts
int count(int face) const; // Function to return number of times a face has appeared
private:
int numx, m, j; //Variables used in functions
};
#endif
The function that requires the class to access itself is below, I know there is no vector called "myVector" but what I'm lost about is the equivalent syntax to be able to perform the operation.
void aHistogram::clear()
{
//Clears bin counts to 0
myVector.at(0) = 0;
myVector.at(1) = 0;
myVector.at(2) = 0;
myVector.at(3) = 0;
myVector.at(4) = 0;
myVector.at(5) = 0;
}
If the function in question isn't overridden in the derived class, you
can just call it:
void HistoGram::clear()
{
at( 0 ) = 0;
// ...
}
This is also true for operators, but you'll have to use (*this) as the
left hand operator:
void HistoGram::clear()
{
(*this)[0] = 0;
// ...
}
If the function or operator is overridden, you'll either have to
qualify the function name,
void HistoGram::clear()
{
std::vector<int>::at( 0 ) = 0;
// ...
}
or cast the this pointer to the base class type:
void HistoGram::clear()
{
(*static_cast<std::vector<int>*>( this ))[0] = 0;
// ...
}
But are you sure that you want public inheritance here? You state that
the size of the vector should always be 6. There's no way you can
guarantee that using public inheritance; at the least, you need private
inheritance, and then using declarations for the operations that you
want to support. (I've a couple of cases where I've needed restricted
std::vector like this, which I've implemented using private
inheritance. And sometimes forwarding functions, when for example
I've wanted to expose only the const version of the function.)
Also: there are very, very few cases where std::vector<>::at is
appropriate. Are you sure you don't want [], with the bounds checking
you get in most modern implementations.
Instead of deriving from std::vector, in this case contain one (as a data member).
The problem with deriving is that it's then possible to treat a Histogram instance as just a std::vector, doing things that invalidate assumptions about the values of added data members.
In more technical jargon, with class derivation you have no guaranteed class invariant above the one provided by std::vector.
As a general rule of thumb, think of data member before class inheritance.
Sometimes inheritance is the thing, even inheritance from standard library container classes (e.g., std::stack is designed for inheritance), but not in this case.
About this: the size of the vector should always be 6.
You probably want to forbid some functionality to the user of the class. For example
vector::push_back
vector::pop_back
vector::insert
are functionalities that can change the size of the vector.
You can achive this by making such functions private members in the child class:
class aHistogram : public vector<int>
{
public:
aHistogram(){};
private:
vector<int>::push_back;
vector<int>::pop_back;
vector<int>::insert;
int numx, m, j;
};

2D vector, overlapping & different types of objects in array

I'm currently pondering how should I go about making a 2D vector array for a sort of a game board.
The board should be vectors because the size can vary, and each "square" should contain information about what objects are in that square.
The problem is that there can be overlapping objects, and the objects may not be the same type or class.
This is what I'm currently considering: (pseudo code)
struct Square {
vector<enum type>;
vector<pointers to objects>;
};
vector< vector <Square> >;
And the pointer's would point to different vector arrays each holding specific objects.
I'm unsure how to make such functionality or if this is even possible, and I'm seriously thinking this might be more complicated then it needs to be..
Some objects must be classes, but I could make all the types of objects in the game board classes that inherit from one master class.. But in the end the objects are completely different so I'm not sure if that makes much of a difference.
Am I just being blind and missing a easier way to do what I'm trying to do: 2D array holding different types of elements that can also overlap in the array?
I'd really appreciate any help, snippets or insight.
Notes:
Board size won't chance after creation.
Objects must be able to move around in the board.
Here's what I would suggest.
#include <boost/shared_ptr.hpp>
class GameObject {
public:
virtual ~GameObject() {}
enum Type {
FOO,
BAR
};
virtual Type type() const = 0;
virtual std::string name() const = 0;
virtual void damaged() {}
};
class FooObject : public GameObject {
public:
Type type() const { return FOO; }
std::string name() const { return "Foo object"; }
void damaged() {
std::cout << "Foo was damaged!" << std::endl;
}
};
class BarObject : public GameObject {
public:
Type type() const { return BAR; }
std::string name() const { return "Bar object"; }
// Bar object doesn't respond to damage: no need to override damaged()
};
class Square {
std::vector<boost::shared_ptr<GameObject> > objects;
};
class Board {
// Details of the implementation here not important, but there
// should be a class to hide them.
Square* squares;
int width, height;
Board(int width, int height) :
squares ( new Square[ width * height ] ),
width ( width ),
height ( height )
{
}
~Board() {
delete [] squares;
}
Square& square(int x, int y) {
if( x < 0 || x >= width || y < 0 || y >= height ) {
throw std::logic_error( "accessed square out of bounds" );
}
return squares[ x + width * y ];
}
};
Summary:
Have a single base class for all sorts of objects that can be placed on a game board.
A class of this type must have a virtual destructor, even if it's trivial. This is because you will be deleting things through GameObject pointers.
If it's necessary to distinguish the game objects, use a virtual method returning a 'type' value.
As far as it's not necessary to use it, don't use that type value, but use other virtual methods that do meaningful things instead. Using the type value (and then generally casting to the subtype) should be considered a last resort. For instance (inventing details about your game freely):
Every object has a name that shows when you put the cursor over it. This is returned in name().
Events in the game may cause 'damage' an object. This only applies to some sorts of objects, so the default action on damaged() is to do nothing. Foo-objects, which respond to damage, override this with an actual action.
However you implement the board, hide your exact implementation away in a class. (Don't take my code as an indication that you shouldn't use vector<> for this, that's definitely fine. I have a slight personal preference against vector< vector<> > here, but that's not too bad either.)
Use shared pointers for the game objects.
Boost has a great and widely used implementation.
If you can't use shared pointers, control the lifetime of your game objects outside the Square class (say, in a master list of all game objects in the Board class), and then use raw pointers in the Square class.
If you do use shared pointers, and it's the first time you do, briefly read up on them first. They're not magic, you need to beware of certain things such as circular references.
Depending on your needs, you may want to have a "backlink" in GameObject to the squares, or the coordinates of the squares, that contain pointers to that GameObject. This will allow you to easily remove objects from the board and move them around.

Polymorphism - Appropriate usage of a pointer to a pure abstract class?

I am implementing a simple board game (Breakthrough) using OpenGL (plus GLUT and GLUI).
I'm thinking of implementing a Board class, which will have a vector<vector<Cell> > as one of its attributes. Cell represents a space in the game board. It can contain a GameObject. GameObject will be a pure abstract class. It mandates that its derivative classes implement render(), for example. Possible derivative classes will be:
Blank, representing an empty space
Pawn, representing a pawn (the only possible pieces in Breakthrough)
The board will be rendered by first rendering the board, then iterating through each Cell, getting its contents and calling render() for each of them.
The only possible way I can think of to achieving this is making the GameObject in Cell a pointer (board[y][x].getContents()->render(), where getContents() returns the GameObject*)
Is this the best way to do this? Is this an appropriate usage of pointers?
Let me promote my comment into an answer. This doesn't mean that it's in any sense complete, only that this allows me to spell out some code examples. My original comment:
That's OK, though you probably would do better with a std::unique_ptr<GameObject> or a std::shared_ptr<GameObject> so you don't get lost amids the manual lifetime management issues. Finally, how about a flat 1-D array accessible in strides?
Here's how I might go about this:
#include <vector>
#include <memory>
struct GameObject { virtual void render() const = 0; virtual ~GameObject() { } };
class Cell
{
std::unique_ptr<GameObject> m_go;
public:
void render() const { m_go->render(); }
Cell() : m_go(new BlankCell) { }
// more functions to reassign the cell value etc.
};
class Board
{
std::vector<Cell> m_board;
std::size_t m_length;
public:
Board(std::size_t length) : m_board(length * length), m_length(length) { }
Cell & cell(std::size_t i, std::size_t j) { return m_board(j + i * m_length); }
Cell const & cell(std::size_t i, std::size_t j) const { return const_cast<Board*>(this)->cell(i, j); }
// more...
}
Yes.
Also, maybe you should use another container for your cells (some kind of matrices or so)

Order of Class Definitions in C++

I've got a bit of a problem here. I'm trying to define several classes, of which some are Players and some are Pawns belonging to the players. Coming from Python, I'm used to being able to conveniently access a Pawn's owning Player through the Pawn, as well as accessing a Player's Pawns through the Player. Correct me if I'm wrong, but this seems impossible in C++.
I currently define Player first, and one of its data members m_Pawns is supposed to be a vector<Pawn>. I declare the data member, but I don't assign it any value. I also define a member function that is meant to assign a vector of pawns to m_Pawns, but I don't call it anywhere near the constructor. Since I'm not actually calling the constructor for Pawn in the constructor for Player, it seems I should be fine.
Here's my Player class. The Board class is defined beforehand, whereas the Pawn class is defined afterwards (the Pawn class contains pointers to an owner of the Player class, so switching it around doesn't really help).
class Player
{
public:
Player(sf::Color color, const string& name);
sf::Color GetColor();
string GetName();
void CreatePawns(Board& board, int which);
protected:
vector<Pawn> m_Pawns;
sf::Color m_Color;
string m_Name;
};
Player::Player(sf::Color color, const string& name):
m_Color(color),
m_Name(name)
{}
sf::Color Player::GetColor()
{
return m_Color;
}
string Player::GetName()
{
return m_Name;
}
void Player::CreatePawns(Board& board, int which)
{
switch(which)
{
case 1:
for(int i = 0; i < 4; ++i)
{
m_Pawns.push_back(Pawn((*board).Cluster1[i], this*, m_Color));
}
break;
case 2:
for(int i = 0; i < 4; ++i)
{
m_Pawns.push_back(Pawn((*board).Cluster2[i], this*, m_Color));
}
break;
case 3:
for(int i = 0; i < 4; ++i)
{
m_Pawns.push_back(Pawn((*board).Cluster3[i], this*, m_Color));
}
break;
default:
cout << "Invalid player ID!\n\n";
break;
}
}
If the class Player is coming first and class Pawn coming later then you can only declare pointer or reference to the later class (here Pawn). You cannot have objects of later class, e.g.
class Player {
Pawn* p; // allowed
Pawn& r; // allowed
vector<Pawn*> p; // allowed
vector<Pawn&> vr; // not allowed (reference are not copyable)
vector<Pawn> o; // error !
};
class Pawn {};
There is no way you can overcome this situation, as in C++ for non-template class one need to show full definition to declare objects.
The only way out is to reformat your code or use pointer/reference (with forward declaration).
The class Pawn still has to be defined so compiled can instantiate vector. You can get away with storing references or pointers to Pawn objects in your vector instead of values; vector for example. In that case forward declaration of class Pawn will be enough.
You can switch it around, because you can forward declare Player, and then Pawn can have a pointer to it.
You can take a pointer to an incomplete type. You can't hold values of that type.
You can do something like this:
class Pawn;
class Player {
}
class Pawn {
}