2D-Array with Polymorphy

I wanna create a field for a little game. The field consists of the followed classes:

Floor
Wall
Door

All 3 of them are derived classes of the abstract class Tile. With it I wanna create the field with 7x7 per Polymorphism. The field should be on the heap so it cannot be vanished by the compiler.

1
2
3
4
const int width = 7;
const int height = 7;

Tile*** field;


How can I create the field?

rumpfi88
I don't really understand what you are trying to do. And why is data on the stack
vanished by the compiler
?
If your field will never change size during a game it might be easier to declare it like this:

 
Tile field = new Tile[7][7];


Tile is a abstract class, you can't create the field like you did, Galik.

But if you read it from a config-file with ifstream, how to create the field dynamicly?
Last edited on
Good point, I should have made an array of pointers.

Well:

Tile* is Tile pointer or array of Tile.

Tile** is array of Tile pointer

Tile*** is array of array of Tile*

So we are dealing with arrays of arrays. So you need to allocate an array and then visit each element of that array to allocate another array to each one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
	const size_t x_size = 7;
	const size_t y_size = 7;

	// Declare an 'Tile***' (array of array of Tile*)
	Tile*** field;

	// Allocate your 'Tile***'
	field = new Tile**[x_size];
	// Every element is a 'Tile**' (array of Tile*)

	// Visit every 'Tile**' element
	for(size_t x(0); x < x_size; ++x)
	{
		// Allocate a 'Tile*' to each 'Tile**' element
		field[x] = new Tile*[y_size];
		// Every element of this array is a 'Tile*' (array of Tile)

		// Visit every 'Tile*' element
		for(size_t y(0); y < y_size; ++y)
		{
			// Allocate a Tile to every Tile* element
			field[x][y] = new Tile;
		}
	}
Tile is a abstract class, you can't create an object of Tile, but of the derived classes.

I already came with the idea of using this:

 
std::vector<std::vector<Tile*>> field;


now a double for-loop

1
2
3
4
5
6
7
8
9
10
11
for(int y = 0; y < height; y+)
{
   field.push_back( std::vector<Tile*>() );
   for(int x = 0; x < width; x++)
   {
      // if Tile from config == Wall
      Tile* tile = new Wall(...);
      field[y].push_back(tile);
      ....
   }
}


This method works, I came with it while I was in University right now. But thanks to all.
closed account (1yR4jE8b)
I'm working on something very similar, so I think I could help you


I'd like to repeat what someone else already said:

vanished by the compiler


lol wut?

Also, I am absolutely disgusted at the sight of a Object***, do you really want to be known as a three star programmer ;-P ?

http://www.c2.com/cgi/wiki?ThreeStarProgrammer

Before you know it you'll be knowing nested #if #elsif macros and no one but you will be able to maintain your code :P.

May I suggest wrapping your "Field" in a class as well, and only using an array of Tile* of size m * n, and accessing your array elements using an overload operator(). It will make things MUCH MUCH easier in the long run, there are also less pointer chases so it is more efficient.

Something like this:

Field.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef _FIELD_H_
#define _FIELD_H_

#include "Tile.h"

class Field
{	
public:
	typedef unsigned int size_type;
	
	Field(size_type rows, size_type cols);
	Field(const Field& other);

	virtual ~Field();
	
	Field& operator=(const Field& other);
	
	Tile* operator()(size_type row, size_type col);
	const Tile* operator()(size_type row, size_type col) const;
	
	
private:
	Tile** grid;
	size_type numRows, numCols;
};

#endif /* _FIELD_H_ */ 


Field.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "Field.h"

Field::Field(size_type rows, size_type cols) :
	grid(new Tile*[numRows * numCols]), numRows(rows), numCols(cols)
{
	//additional implementation ommited
}

Field::Field(const Field& other) :
	grid(new Tile*[other.numRows * other.numCols]), numRows(other.numRows), numCols(other.numCols)
{
	//additional implementation ommited
}

Field::~Field()
{
	//additional implementation ommited
}

Field& Field::operator=(const Field& other)
{
	if(this != &other)
	{
		//additional implementation ommited
	}
	return *this;
}

/** This is the important bit right here **/

Tile* Field::operator ()(size_type row, size_type col)
{
	return grid[row * numCols + col];
}

const Tile* Field::operator ()(size_type row, size_type col) const
{
	return grid[row * numCols + col];
}




Last edited on
Topic archived. No new replies allowed.