Итерация имен объектов в C++
Как можно перебирать массив для манипулирования или доступа к различным объектам и их функциям-членам? У меня есть 10 предметов. Прямо сейчас у меня есть один и тот же код, который обращается к каждой функции-члену объекта и манипулирует данными объекта, которые в основном копируются и вставляются для каждого объекта. Мне просто интересно, есть ли способ использовать цикл, чтобы написать этот код один раз и сделать так, чтобы он перебрал все 10 объектов.
Вместо того, чтобы делать это вручную, как показано ниже:
Color red.set();
Color green.set();
Color blue.set();
Color yellow.set();
Color purple.set();
...
Есть ли способ сделать это с помощью цикла, например:
colors[5] = {"red", "green", "blue", "yellow", "purple", ...};
for(int i = 0; i < 10; i++){
Color colors[i].set();
}
Я знаю, что для PHP сделать что-то подобное было бы так:
$colors = array("red", "green", "blue", "yellow", "purple" ...);
for($i = 0; $i < 10; $i++){
${$colors[$i]} = $colors[$i];
// $red = "red";
}
Возможно ли сделать это для C++?
Ниже приведен еще один пример того, почему я спрашиваю об этом и к чему я обращаюсь: вместо:
if(grid[row][col].ship == "red")
{
red.setShipDamage();
if(red.getShipSunk() == true)
red.destroy();
}
else if(grid[row][col].ship == "green")
{
green.setShipDamage();
if(green.getShipSunk() == true)
green.destroy();
}
else if( ... )
Чтобы сделать все это один раз в цикле:
for(int i = 0; i < 10; i++)
{
if(grid[row][col].ship == colors[i])
{
**colors[i]**.setShipDamage();
if(**colors[i]**.getShipSunk() == true)
**colors[i]**.destroy();
}
}
4 ответа
Ваш вопрос несколько сбивает с толку. Вам необходимо указать, что делает класс Color. Это то, что вы хотите?
Color colors[5];
char *color_txt[5] = {"red", "green", "blue", "yellow", "purple"};
for (int i = 0; i < 5; i++){
colors[i].set(color_txt[i]);
}
Основываясь на отредактированном вопросе, вы можете создать массив объектов, как я описал:
Color colors[10];
Предполагая, что каждый объект имеет конструктор по умолчанию. Затем вы можете получить доступ к каждому объекту через индекс в массиве. Итак, ваш пример работает как положено:
for(int i = 0; i < 10; i++)
{
if(grid[row][col].ship == colors[i])
{
colors[i].setShipDamage();
if(colors[i].getShipSunk() == true)
colors[i].destroy();
}
}
Кроме того, ваш класс Color должен иметь переопределенный оператор равенства.
Вам нужно сделать что-то вроде этого:
std::map<std::string, Color*> colors;
colors["red"] = &red;
colors["green"] = &green;
colors["blue"] = &blue;
colors["purple"] = &purple;
///....
Color *color = colors[grid[row][col].ship];
color->setShipDamage();
if(color->getShipSunk() == true)
color->destroy();
Я надеюсь, что это помогает.
Не совсем понятно, что вы хотите сделать, но вот удар по этому:
Color red, green, blue, yellow, purple;
Color *colors[5] = {&red, &green, &blue, &yellow, &purple};
for (int i = 0; i < 5; i++) {
colors[i]->set();
}
Ваш пример запутан и плохо спроектирован с самого начала. Если сетка просто хранит ссылки (ну, фактически, указатели) на корабли, вам не нужно было бы зацикливаться для начала! Рассматривать:
if (Ship* ship = grid[y][x].ship()) {// ship() returns nullptr if there's no ship
ship->setDamage();
if (ship->sunk())
// ...
}
Если, с другой стороны, вы хотите связать строки с кораблями, вам нужен ассоциативный контейнер, например unordered_map
из стандартной библиотеки:
Ship red, green, blue, white;
std::unordered_map<std::string, Ship*> = { { "red", &red },
{ "green", &green },
/* ... */ };