Поэтому я пытаюсь создать 2-мерный массив указателей на объект типа Piece. Проблема в том, что когда я пытаюсь назначить указатель на кусок массиву, я получаю ошибку сегментации. Я понял, что мне нужно инициализировать массив до того, как я начну выделять, но я не могу понять это правильно.
Вот файл заголовка карты, который содержит 2-мерный массив указателей.
#ifndef MAP_H
#define MAP_H
#include <iostream>
#include <vector>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <string>
#include <cstring>
#include "Player.h"
#include "Sprite.h"
#include "Piece.h"
#include "Messages.h"
#include "PieceType.h"
using namespace std;
class Map
{
private:
Piece*** pieces;
int startingX;
int startingY;
int width;
int height;
string mapName;
public:
Map(string);
~Map();
void printMap() const;
Piece* pieceType(char);
void setSprite(Piece*);
void firstMove();
void resetMap(string);
bool moveUp(int, int);
bool moveDown(int, int);
bool moveLeft(int, int);
bool moveRight(int, int);
int getHeight();
int getWidth();
};
#endif
Массив, о котором я говорю, это кусочки.
Я пытаюсь выделить это в конструкторе карты.
Map::Map(string name)
{
ifstream map;
string line;
string dimention;
mapName = name;
map.open(name.c_str());
if (map.good())
{
getline (map, line);
int i = 0;
while(line[i] != 'X')
{
dimention[i] = line[i];
i++;
}
stringstream convert(dimention);
convert >> width;
int temp = i;
dimention = "";
i = 1;
while(line[(i + temp)] != '\0')
{
dimention[i] = line[(i + temp)];
i++;
}
stringstream convertTwo(dimention);
convertTwo >> height;
for (int i = 0; i < height; i++)
{
if (!(map.eof()))
{
getline (map, line);
}
else
{
cout << "Error with file" << endl;
break;
}
for (int j = 0; j < width; j++)
{
pieces[i][j] = pieceType(line[j]); //This is where I'm getting the segmentation fault
cout << "assigned" << endl;
if ((pieces[i][j])->getType() == WAYPOINT)
{
if (pieces[i][j]->getWaypointType() == 0)
{
startingX = j;
startingY = i;
}
}
else
{
(pieces[i][j])->setXCordinate(j);
(pieces[i][j])->setYCordinate(i);
}
}
}
}
}
Где имя - это строка, в которой содержится имя файла, который имеет информацию для загрузки определенной карты.
Также функция themeType выглядит следующим образом:
Piece* Map::pieceType(char type)
{
Piece* temp;
if (type == '.')
{
return NULL;
}
if (type == 'S')
{
temp = new Waypoint(0);
return temp;
}
if (type == 'E')
{
temp = new Waypoint(1);
return temp;
}
}
Waypoint - производный класс Piece.
Проблема в том, что вы должны инициализировать этот массив. Как это:
pieces=new Piece**[height];
for(int i=0;i<height;i++){
pieces[i]=new Piece*[width];
}
Напишите это сразу после того, как вы получите width
и height
, и прежде чем начинать использовать pieces
. Но что-то, что вы должны знать: для каждого new
должно быть соответствующее delete
, иначе эта память никогда не будет освобождена, и вы получите утечку памяти. Чтобы освободить эту память, добавьте это в свой деструктор:
for(int i=0;i<height;i++){
for (int j = 0; j < width; j++){
delete pieces[i][j];
}
delete[] pieces[i];
}
delete[] pieces;
Это предполагает, что каждая часть pieces[i][j]
содержит либо объект, выделенный new
либо NULL, и он работает с обоими. Глядя на ваш код, это кажется вашим делом. Однако это не сработает, если один из них не назначен (не ваше дело).
Используйте std::vector<std::vector<Pieces>>
вместо (пытается, потому что он не работает) изобретает колесо. Это безопасно, легко и позволяет избежать головных болей от ручного управления памятью.