2014-01-21 2 views
1

После поиска Google и StackOverflow в течение 2-х дней я не нашел ничего ещеC++ массива с пользовательскими объектами

Я работал с Явой около года, и теперь я решил создать игру на C++ для практики

В java это должно работать, но на C++ это дует мой разум.

У меня есть этот код

Item* inventory = new Item[24]; 

Это массив (инвентаризации), которая содержит элементы

Когда я выделяю динамически массив всех его postions равны нулю? А если нет, могу ли я сделать их пустыми?

А вот код для добавления элемента в первой пустой позиции (забрать товар)

void Inventory::addItem(Item it){ 
    if(isFull()){ 
     cout << "Full inventory" << endl; 
    }else{ 
     for(int i = 0; i<length; i++){ 
      if(inventory[i] == nullptr){ // need this to work somehow 
        inventory[i] = it; 
      } 
     } 
    } 
} 

Он должен быть массиву не вектор, поскольку он имеет фиксированный размер

+0

Какая ошибка? То, как вы объявили свой массив, должна быть выбрана строка 'inventory [i] = it', которая бросает ошибку. – Proxy

ответ

5

Когда я распределить динамически массив, все его позиции равны нулю? А если нет, могу ли я сделать их нулевыми?

В C++ нет такого объекта, как нулевой объект, как в Java. Вместо этого вы можете указать указатель nullptr. В вашем случае объекты по умолчанию сконструированы и, следовательно, не равны нулю.

Он должен быть массиву не вектор, поскольку он имеет фиксированный размер

Вы вообще не хотите, чтобы динамически выделять, если это не является строго необходимым. Используйте std::array, если вы действительно хотите массив фиксированного размера.

То, что я хотел бы предложить использовать std::array в сочетании с std::unique_ptr:

std::array<std::unique_ptr<Item>, 24> arr; 

По умолчанию все std::unique_ptr s будет nullptr.Когда вам нужно выделить объект, который будет в состоянии сделать:

arr[i] = std::unique_ptr<Item>(new Item(...)); 

Вы даже можете создать псевдоним для смарт-указатель:

using item_ptr = std::unique_ptr<Item>; 

, который поможет вам переписать код, как:

std::array<item_ptr, 24> arr; 
arr[0] = item_ptr(new Item(...)); 

В качестве альтернативы вы можете также использовать boost::optional (или std::optional от C++ 14):

std::array<std::optional<Item>> arr; 

Вы сможете проверить, если конкретный i элемент «нуль» (в том смысле, Java) с:

if (arr[i]) 
    // not null 

, и вы будете иметь возможность присвоить значение с:

arr[i] = Item(...); 

и получить его с *arr[i], arr[i]->member_function(...); или arr[i]->member_object.

+0

один вопрос, мне нужно освободить или удалить этот уникальный_ptr? –

+0

@LittleJacod, nope. В этом весь смысл класса: автоматизировать удаление ресурса. – Shoe

2

Вопреки вашему окончательному комментарию, это, по-видимому, вполне разумное приложение для std::vector.

Как сейчас, вы пытаетесь создать массив из N объектов, но затем у некоторых из них фактически есть пустые/несуществующие объекты.

На самом деле это не сбор за фиксированный размер. Это коллекция с переменным размером до определенного указанного максимума. В данный момент игрок может нести 1 предмет или 10, но есть некоторое максимальное количество предметов, которые они могут нести. Они не, однако, постоянно несут максимальное количество элементов, а некоторые из них являются нулевыми объектами .

С учетом того, с чем вы имеете дело, это коллекция с переменным размером (до указанного максимума), std::vector идеально подходит для счета. Поскольку вы имеете дело с классом Item, вероятно, разумно предположить, что фактическими элементами будут экземпляры конкретных классов, которые происходят от Item. В этом случае вам действительно нужно хранить (несколько разновидностей) указатель в массиве, а не фактические объекты Item (иначе каждый производный элемент, который вы пытаетесь поместить в массив, будет «нарезанным», чтобы стать фактическим объектом Item, а не производный объект, когда он хранится в массиве).

Вы можешь сделать это путем создания коллекции unique_ptr с (или другими различными другими умными типов указателей, такими как shared_ptr), но я бы вообще рекомендую в такой ситуации вы считаете Boost ptr_vector типа вместо ,

Что касается ограничения размера, вы, вероятно, захотите создать небольшой класс-оболочку для обработки этого. Это не совсем сложная задача, но лучше всего централизовать этот код в одном месте, а не дублировать код проверки размера везде, где вы можете добавить элемент в инвентарь.

template <class T> 
class inventory { 
    ptr_vector<T *> items; 
    size_t max; 
public: 
    inventory(size_t max) : max(max) {} 
    push_back(T *t) { 
     if (items.size() < max) 
      items.push_back(t); 
    } 

    // other miscellany here. 
}; 

Это возможно, однако, что вы не имеют полиморфный иерархию Item с. Вместо этого у вас только один фиксированный тип для всех элементов в инвентаре, каждый из которых имеет имя и т. Д. Если это так (т. Е. Все Item s действительно являются одним и тем же типом объекта), нет причин вмешиваться в указатели или ptr_vector. Вы действительно просто хотите std::vector<Item>. Однако, как и прежде, вы, несомненно, хотите централизовать код, чтобы обеспечить максимальный размер инвентаря (и, возможно, также предоставить другие услуги, связанные с инвентаризацией).


  1. Если вы позволите мне экскурс, тот факт, что кто-то даже рассматривать такую ​​возможность указывает на степень, в которой с помощью Java деформирует сознание людей и разрушает их способность ясно мыслить. Перефразируя Дейкстра, преподавание Явы должно быть уголовным преступлением.
+0

Следует заметить, что с помощью этого метода вы не сможете иметь чередующиеся «нулевые объекты» (в смысле Java, давайте не будем педантичными) и действительные объекты. – Shoe

+0

@Jefffrey: Конечно, это избегает таких отвратительных беспорядков. –

+1

Я не слишком уверен в том, что вектор настолько очевиден здесь. Просто думая о играх RPG, всегда приятно организовать инвентарь игрока, например: http://media.indiedb.com/images/games/1/17/16438/inventory.png. Это, очевидно, означает, что элементам нужен индекс для размещения их в данном слоте. Векторное решение не допускало бы пустых слотов, если только не заменив специальные «пустые» элементы. – SirDarius

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