Итерация имен объектов в 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 },
                                           /* ... */ };
Другие вопросы по тегам