2013-10-14 5 views
0

Я понимаю основы указателей и ссылок, но самая большая проблема, которую я имею, заключается в том, чтобы решить, когда они должны использоваться (и какие). Основной пример, который я приведу, - одна из основных игр. Предположим, что установка что-то вроде:Классы указателей против ссылки

  • новый Мир
    • камеры
    • Карта

World является указателем, потому что каждый раз, когда игра начинается новый сохранить или загружает существующий один, он удаляет мир и загружает новый. Но внутри Мира, только одно существование камеры и карты должно когда-либо существовать и только на протяжении всего Мира. Если мир разрушен, то, очевидно, они должны быть такими же. Однако .. позволяет сказать, что Map необходимо получить доступ к камере (но также и к другим объектам), должна ли камера передаваться по ссылке на карту или как указатель, или? Например, если его предполагается по ссылке, она должна быть:

map = Map(&camera); 
(inside map class) Map(Camera camera) {...} 

Или еще как:

map = Map(camera); 
(inside map class) Map(Camera &camera) {...} 

Кроме того, позволяет сказать, что карта имеет 2D вектор плитки под названием сетки. Что-то вроде:

std::vector< std::vector<Tile> > > grid; 

Теперь давайте говорить у меня есть класс, который должен PathFinder, что сетка передается в Необходимо отредактировать плитки непосредственно изменить F, G, и т.д. значения (для первопрохождения).. Должен ли этот 2D-вектор быть нормальным двумерным вектором Tile's, а вся вещь передана ссылкой на PathFinder? Или это должен быть 2D-вектор указателей Tile?

Кроме того, у NPC и Player будет текущий ток, который является плиткой, в которой они сейчас находятся. Они должны иметь ссылку или указатель на эту плитку, чтобы они могли также установить себя в качестве водителя или пассажира на этой плитке через что-то вроде этого внутри классов NPC/игрока:

currentTile = tile; 
currentTile->SetOccupant(this); 

Другая проблема приходит, когда я тогда уничтожить эту сетку, чтобы загрузить новую карту, как мне легко справиться с тем, чтобы убедиться, что ничто не указывает на Плитки, которые больше не существуют. Нужно ли просто перебирать эти классы и устанавливать currentTile в NULL?

Здесь я начал действительно путаться этим материалом. Любая помощь приветствуется, поскольку я, очевидно, довольно nooby. @ _ @; И извините, если это действительно не тема игры. Если вам нужно переместить его на другой стек, просто сообщите мне или переместите его (если можете). > _ <

+2

Проголосовали за принадлежность к StackOverflow, так как это действительно вопрос о лучших практиках C++. На боковой ноте вектор векторов для 2D-сетки довольно плох; просто используйте один вектор и вычислите смещения внутри него вручную (или напишите простую оболочку). –

+0

@SeanMiddleditch Спасибо за подсказку о векторе векторов. Не понял, что это плохо. Просто сделал интерфейс к моей сетке плитки, которая вычисляет смещение, так что это всего лишь один вектор. ^^; – Zyaga

ответ

1

Рассмотрите класс карты. Вы можете передать камеру по ссылке или в виде указателя. Это действительно не имеет значения. Важно то, что происходит с передачей камеры. Собираетесь ли вы назначить ее члену, который является Camera *? В противном случае установка камеры в конструкторе не будет достигнута. Вам нужно будет указать указатель/ссылку камеры при каждом вызове Карты, требующей камеры.

Для хранения объектов плитки одно измерение std :: vector <> будет прекрасно. Используя некоторую простую математику, эту сетку черепицы можно пройти довольно легко. Вложение другого вектора внутрь приведет к ненужным накладным расходам.Вот алгоритм выборки для этого:

std::vector<Tile> tiles = makeTiles(); 
for (int y=0; y<mapHeight; y++) 
{ 
    for (int x=0; x<mapWidth; x++) 
    { 
     Tile tile = tiles.at(x + y*mapWidth); 
     tile.doSomethingWithTile(); 
    } 
} 

Принятие решения о том, как получить данные плитки из вашей карты в Навигаторе действительно вопрос о том, как хорошо вы хотите, чтобы защитить данные вашей карты. Предоставляя ссылку на все данные плитки, вы по существу делаете ее общедоступной. Поскольку Навигаторе необходимо редактировать отдельные плитки, но не вся плитка сам массив, лучший подход будет иметь метод, как это:

Tile* Map::AccessTile(int tx, int ty); 

Таким образом, весь вектор данных плитки не подвергается, но PathFinder сможет получить то, что ему нужно. Кроме того, Map :: AccessTile() может быть закрытым, а PathFinder объявлен другом в Map. Другой подход заключается в предоставлении таких методов, как Map :: SetTileF (int tx, int ty, float f). Это может быть утомительным, хотя.

Для NPC и Player аналогичное решение доступно. На самом деле им не нужно иметь прямой доступ к записи, на которой они находятся. Добавьте такой метод, как Map :: SetTileOccupant (Entity * entity) и соответствующий Map :: GetTileOccupant().

Теперь вы беспокоитесь об удалении объектов. Вы должны взглянуть на некоторые из эмулируемых указателей, предоставленных C++ (в частности, std::shared_ptr<> и std::weak_ptr<>). Быстрое объяснение этого - shared_ptr - это указатель, который «владеет» объектом, а weak_ptr знает, куда обращаться к объекту, но фактически не «владеет» объектом.

С помощью этих указателей эмулировать, вы можете сделать что-то вроде следующего:

//prototype for setWorld 
//note that shared_ptr<> casts to weak_ptr<> nicely 
Camera::setWorld(std::weak_ptr<World> world); 

//setup the camera and world 
std::shared_ptr<World> world(new World); 
Camera camera; 
camera.setWorld(world); 

С кода выше, камера имеет указатель на мир. Если мир будет удален по какой-то причине, камера может понять это с помощью следующего метода:

bool Camera::worldIsValid() 
{ 
    return (this->mWorld.expired() == false); 
} 

Кроме того, вы герметизирующая камеры внутри мира, и это, вероятно, что-то вам не нужно делать. Вместо этого камера может быть автономной и просто ссылаться на мир, когда ему нужна информация об этом или Карта, содержащаяся в World.

+0

Только один последний проясните, если вы не возражаете. Должна ли Map быть указатель внутри мира (или просто нормальная переменная), если я хочу, чтобы он продлил продолжительность Мира и также захотел передать его другим членам/классам мира? Я предполагаю, что если я * не * сделаю его указателем, он потеряет область видимости? – Zyaga

+0

Вы можете сделать это указателем, но это не имеет значения. Если вы объявите его как карту или карту *, она будет продолжаться до тех пор, пока объект World все еще находится вокруг. Очевидно, что если у вас есть карта *, вам придется вручную создать объект с помощью нового оператора. Если вы хотите использовать shared_ptr <>, тогда карта должна быть объявлена ​​как shared_ptr . –

Смежные вопросы