Цикл по объектам класса с ++ - PullRequest
0 голосов
/ 27 ноября 2018

Итак, у меня есть класс с 120 объектами, и каждый объект имеет одинаковые переменные-члены.Примерно так:

Area f1;Area f2; Area f3; Area f4; Area f5; Area f6; [...]

f1.SetCoal(1);
f2.SetCoal(0.7); f2.SetCoal(.3);
f3.SetCoal(.5950); f3.SetCopper(0.2833); f3.SetIron(0.0917); f3.SetAmber(0.025); f3.SetGold(0.005);
f4.SetCoal(.5425); f4.SetCopper(0.325); f4.SetIron(0.1025); f4.SetAmber(0.0225); f4.SetGold(0.0075);
f5.SetCoal(.49); f5.SetCopper(0.3667); f5.SetIron(0.1133); f5.SetAmber(0.02); f5.SetGold(0.01);
f6.SetCoal(.4375); f6.SetCopper(0.4083); f6.SetIron(0.1242); f6.SetAmber(0.0175); f6.SetGold(0.0125);  [...]

Таким образом, некоторые из этих областей становятся «активными» при вводе пользователем, устанавливая переменную-член в значение TRUE.Можно ли обойти все объекты и проверить, активны ли они?

for (int i = 0; i <= 119; i++)
{

     if(f(i).active == true) 
     //do stuff
}

вместо

if(f1.active) //do stuff
if(f2.active) //do stuff
if(f3.active) //do stuff

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

Вы можете сделать std::vector всех ваших областей и инициализировать их начальными значениями с помощью списка инициализаторов.Затем вы можете зациклить их, используя диапазон, основанный на цикле.

#include <vector>

class Area {
    double m_coal;
    double m_copper;
    double m_iron;
    double m_amber;
    double m_gold;

    bool m_active;
public:
    Area(double coal, double copper, double iron, double amber, double gold) :
        m_coal(coal), m_copper(copper), m_iron(iron), m_amber(amber), m_gold(gold), m_active(false)
    {}
    bool is_active() const { return m_active; }
};

int main() {
    // initialize all areas
    std::vector<Area> areas = {
        {1., 0., 0., 0., 0.},
        {0.7, 0., 0., 0., 0.},
        {.5950, 0.2833, 0.0917, 0.025, 0.005}
    };

    for (auto& area : areas) {
        if (area.is_active()) {
            // do stuff
        }
    }
}

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

#include <iostream>
#include <initializer_list>
#include <array>
#include <vector>

// append to the list when you invent a new resource
enum Resource : size_t { coal, copper, iron, amber, gold, LAST=gold, COUNT=LAST+1 };

class Area {
    std::array<double, Resource::COUNT> m_resources;
    bool m_active;
public:

    Area(std::initializer_list<double> il) :
        m_resources(),
        m_active(false)
    {
        std::copy(il.begin(), il.end(), m_resources.begin());
    }

    double get(Resource x) const { return m_resources[x]; }
    void set(Resource x, double value) { m_resources[x]=value; }
    void add(Resource x, double value) { m_resources[x]+=value; }

    void set_active() { m_active=true; }
    void set_inactive() { m_active=false; }
    bool is_active() const { return m_active; }
};

int main() {
    // initialize all areas
    std::vector<Area> areas = {
        {1.},
        {0.7},
        {.5950, 0.2833, 0.0917, 0.025, 0.005},
        {.1232, 0.3400, 0.0000, 0.234, 0.001}
    };

    areas[0].set_active(); // just for testing
    for (auto& area : areas) {
        if (area.is_active()) {
            // do stuff
            std::cout << "coal before: " << area.get(coal) << "\n";
            area.add(coal, -0.1);
            std::cout << "coal after : " << area.get(coal) << "\n";
        }
    }
}
0 голосов
/ 27 ноября 2018

Вы можете использовать препроцессор C ++, возможно с Boost.Preprocessor расширение библиотеки:

#include <iostream>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/comparison/not_equal.hpp>
#include <boost/preprocessor/repetition/for.hpp>
#include <boost/preprocessor/tuple/elem.hpp>

#define PRED(r, state) \
  BOOST_PP_NOT_EQUAL( \
    BOOST_PP_TUPLE_ELEM(2, 0, state), \
    BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(2, 1, state)) \
  ) 

#define OP(r, state) \
  ( \
    BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(2, 0, state)), \
    BOOST_PP_TUPLE_ELEM(2, 1, state) \
  ) 

#define INIT(r, state) \
  BOOST_PP_CAT(x.var, BOOST_PP_TUPLE_ELEM(2, 0, state)) = \
    BOOST_PP_TUPLE_ELEM(2, 0, state));

#define PRINT(r, state) \
 std::cout << BOOST_PP_CAT(x.var, BOOST_PP_TUPLE_ELEM(2, 0, state)) << ", ";

struct X {
    int var1, var2, var3, var4, var5;
};

int main() {
    X x;
    BOOST_PP_FOR((1, 5), PRED, OP, INIT)
    BOOST_PP_FOR((1, 5), PRED, OP, PRINT)
}

Обратите внимание, что это просто демонстрация того, как перебирать (член) переменные с именем varI, где I - от 1 до 5. В конечном итоге вы можете изменить его для своей проблемы.

Также обратите внимание, что такое решение ужасно уродливо и его трудно поддерживать.Я только что опубликовал это , потому что это может быть сделано , но настоятельно рекомендовал бы хранить эти переменные в некоторой форме массива, как предложили другие.

Демонстрация в реальном времени: https://wandbox.org/permlink/rpGg9iKVkrI3SCtM

0 голосов
/ 27 ноября 2018

Попробуйте что-то вроде этого:

#include <vector>

std::vector<Area> f(120);

f[0].SetCoal(1);
f[1].SetCoal(0.7); f[1].SetCoal(.3);
f[2].SetCoal(.5950); f[2].SetCopper(0.2833); f[2].SetIron(0.0917);
//...

for(auto & a: f)
{
     if(a.active == true) 
     //do stuff
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...