как добавить значение в enum?
От: Korchy  
Дата: 18.06.10 12:57
Оценка: 1 (1)
Подскажите, пожалуйста, есть класс, объект которого может выполнять 2 действия (стоять и бежать), названия которых я указываю в перечислении
class1 {
public:
enum Action {stay,run};
}

когда я наследую от него другой класс, объект которого должен выполнять еще одно действие (допустим, прыгать), как мне добавить его в список enum? Только переопределяя перечисление заново?
class2:public class1 {
public:
enum Action {stay,run,jump};
}

Или можно по другому как-то? А если классов-наследников много, stay и run должны копироваться в каждый? Или здесь вообще enum не к месту и нужно использовать что-то другое?
Re: как добавить значение в enum?
От: dilmah США  
Дата: 18.06.10 13:39
Оценка:
K>Или можно по другому как-то? А если классов-наследников много, stay и run должны копироваться в каждый? Или здесь вообще enum не к месту и нужно использовать что-то другое?

по стандарту, размер энума (сколько бит на него выделить) определяется при определении. То есть компилятор имеет право выделить, скажем, 8 бит, если исходно все элементы в них укладываются. Соответственно в дальнейшем это ограничение не преодолеть.
Re: как добавить значение в enum?
От: zaufi Земля  
Дата: 18.06.10 13:53
Оценка:
я не оч понимаю зачем этим объектам enum... чтоли он буит передваться как параметр в какуюнить виртуальную функцию?? типа do_action(run) или там do_action(jump)??

т.к. описания задачи нет то в голову приходит оч много вариантов рассказывать которые бессмысленно не зная зачем все это надо...
ну а по теме вопроса... ну да: в enum нельзя добавлять значения в наследниках... по сути ты определяешь новый enum c таким же именем что в последующем заставить тебя пользоваться full qualified именами для доступа к ним, что в конечно итоге приведет к аццкой путанице ибо run буит у базового класса и другие runы будут у наследников... кроме того это потребует усилий по синхронизации значений этих runов ибо ничто не помешает тебе придать им (случайно в том числе) разные значения... -- вопщем попахивает проблемами %)

доопределять можно например mplные сиквенсы -- ну т.е. в базовом классе заводим
struct base
{
    typedef boost::mpl::vector<run, stay> actions;
};

и в наследниках делаем

struct child : public base
{
    typedef boost::mpl::push_back<base::actions, jump> actions;
};


где действия run, stay, jump могут быть как просто пустыми структурами (ну типо тэги) так и например typedefами на boost::mpl::int_<> если хочется какогото числового значения...

ну а в целом чтобы полноценно рассказать о других способах надо знать чего ты хочешььь сделать...
Re: как добавить значение в enum?
От: Sni4ok  
Дата: 18.06.10 15:07
Оценка:
Здравствуйте, Korchy, Вы писали:

K>Или можно по другому как-то?


используйте статические интегральные константы

class1 {
public:
static const int stay = 0;
static const int run = 1;
};
class2:public class1 {
public:
static const int jump = 2;
};
Re: как добавить значение в enum?
От: Vain Россия google.ru
Дата: 18.06.10 16:35
Оценка:
Здравствуйте, Korchy, Вы писали:

K>Подскажите, пожалуйста, есть класс, объект которого может выполнять 2 действия (стоять и бежать), названия которых я указываю в перечислении

K>...
K>Или можно по другому как-то? А если классов-наследников много, stay и run должны копироваться в каждый? Или здесь вообще enum не к месту и нужно использовать что-то другое?
Ну можно так:
class class1 {
public:
  enum Action {stay,run};
  static const int LastAction = run;
};

class class2:public class1 {
public:
  enum Action {jump=LastAction+1,sit};
};
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[2]: как добавить значение в enum?
От: Turyst  
Дата: 18.06.10 16:41
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>ну а в целом чтобы полноценно рассказать о других способах надо знать чего ты хочешььь сделать...


Из сообщения я так подозреваю, что автор пишет конечный автомат, или просто хочет хранить состояние обєкта.
Re[2]: как добавить значение в enum?
От: Korchy  
Дата: 18.06.10 19:51
Оценка:
моя задача состоит в том, чтобы реализовать удобное управление объектами. Каждый объект описывается классом. Например класс автомобиля Car, человека Human. Каждый из них может выполнять разные действия. Машина — двигаться вперед и назад, человек тоже двигаться и прыгать. Действия могут комбинироваться (прыжок + движение вперед). Чтобы это реализовать мне пришло в голову только сделать массив действий vector в который я заношу что список действий. В программе я каждую секунду пробегаю этот список и проверяю, какие действия там есть и еще не завершились и через case их обрабатываю.
for(std:vector<Action*>:iterator i;begin;end)
switch case *i->id = run...

действия я поименовал через enum просто для наглядности. Мне хотелось сделать некий перечень действий, в который я в каждом классе мог бы добавлять новые действия (как прыжки для человека) и переопределив функцию-обработчик добавить в нее новый case для обработки нового действия. enum же я попытался использовать чтобы хотя бы внутри класса не думать о том, что 1 — это прыжок, а 455 — "тройной тулуп" и т.д.

оверквотинг и топпостинг — deleted. — Кодт
Re[2]: как добавить значение в enum?
От: Korchy  
Дата: 18.06.10 19:52
Оценка:
Спасибо, подумаю над этим вариантом.
Re[2]: как добавить значение в enum?
От: Korchy  
Дата: 18.06.10 19:54
Оценка:
В этом случае class2::Action не будет иметь значений stay и run, а только jump=2 и sit=3. Мне же нужно чтобы в class2::Action были все четыре значения.
Re[3]: как добавить значение в enum?
От: Korchy  
Дата: 18.06.10 19:56
Оценка:
Да, нечто похожее на конечный автомат.

оверквотинг и топпостинг — deleted. — Кодт
Re[2]: как добавить значение в enum?
От: Korchy  
Дата: 18.06.10 19:59
Оценка:
В классе-наследнике, если не ошибаюсь, снова будет выполнена операция определения размера и будет выделено столько памяти, сколько нужно. Проблема в том, что для этого enum нужно копировать целиком из класса-предка и добавлять значения в него. Получается жуткое дублирование кода и путаница, как следствие. Мне хотелось этого избежать.

оверквотинг и топпостинг — deleted. — Кодт
Re: как добавить значение в enum?
От: Seigram  
Дата: 18.06.10 20:09
Оценка:
Здравствуйте, Korchy, Вы писали:

K>Подскажите, пожалуйста, есть класс, объект которого может выполнять 2 действия (стоять и бежать), названия которых я указываю в перечислении

K>
K>class1 {
K>public:
K>enum Action {stay,run};
K>}
K>

K>когда я наследую от него другой класс, объект которого должен выполнять еще одно действие (допустим, прыгать), как мне добавить его в список enum? Только переопределяя перечисление заново?
K>
K>class2:public class1 {
K>public:
K>enum Action {stay,run,jump};
K>}
K>

K>Или можно по другому как-то? А если классов-наследников много, stay и run должны копироваться в каждый? Или здесь вообще enum не к месту и нужно использовать что-то другое?

Есть на codeproject тема SmartEnum, но мне кажется не слишком удачной.
А вообще традиционно используют константы, или как уже сказанно инициализируют перечесляемый тип начиная со значения конечного элемента "наследуемого".

class base {
  enum EAction { super = 0 };
  static const stay = super+1;
  // etc...
  virtual some_method(EAction act) =0;
};
Re[3]: как добавить значение в enum?
От: zaufi Земля  
Дата: 18.06.10 20:17
Оценка: 1 (1) -1
Здравствуйте, Korchy, Вы писали:

K>моя задача состоит в том, чтобы реализовать удобное управление объектами. Каждый объект описывается классом. Например класс автомобиля Car, человека Human. Каждый из них может выполнять разные действия. Машина — двигаться вперед и назад, человек тоже двигаться и прыгать. Действия могут комбинироваться (прыжок + движение вперед). Чтобы это реализовать мне пришло в голову только сделать массив действий vector в который я заношу что список действий. В программе я каждую секунду пробегаю этот список и проверяю, какие действия там есть и еще не завершились и через case их обрабатываю.

K>for(std:vector<Action*>:iterator i;begin;end)
K>switch case *i->id = run...

K>действия я поименовал через enum просто для наглядности. Мне хотелось сделать некий перечень действий, в который я в каждом классе мог бы добавлять новые действия (как прыжки для человека) и переопределив функцию-обработчик добавить в нее новый case для обработки нового действия. enum же я попытался использовать чтобы хотя бы внутри класса не думать о том, что 1 — это прыжок, а 455 — "тройной тулуп" и т.д.


ну вот что мне видится: ты имеешь набор разрозненных объектов объединять которые в единую иерархию нет никогого смысла ибо и свойства и действия у них оч разные. одно из решений на вскидку:

#include <boost/current_function.hpp>
#include <boost/function.hpp>
#include <boost/bind/apply.hpp>
#include <boost/bind.hpp>
#include <algorithm>
#include <iostream>
#include <vector>

struct car
{
    void start() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; }
    void stop() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; }
};
struct human
{
    void eat() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; }
    void shit() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; }
};
struct tiger
{
    void jump() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; }
    void eat() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; }
};

int main()
{
    car c;
    human h;
    tiger t;

    typedef std::vector<boost::function<void()> > actions;
    actions a;
    a.push_back(boost::bind(&car::start, c));
    a.push_back(boost::bind(&human::eat, h));
    a.push_back(boost::bind(&tiger::jump, t));
    a.push_back(boost::bind(&human::shit, h));
    a.push_back(boost::bind(&car::stop, c));
    a.push_back(boost::bind(&tiger::eat, t));

    std::for_each(a.begin(), a.end(), boost::bind(boost::apply<void>(), _1));
    return 0;
}


просто заводим контейнер с действиями которые дребуется выполнять и bindим в него объекты и методы. если приспичит можно писать более сложные функторы кторые будут действовать над несколькими объектами одновременно или выполнять несколько действий над одним (ну типа бежать и прыгать) -- как захочется в общем...

таким образом никакие енумы нафиг не нужны и соответсна не придется их синхронизировать а также не нада буит постоянно модифицировать switch втыкая в него реакцию на новые действия и вообще от самих объектов ничего не требуется (ну разве что наличие экземпляра)
Re[3]: как добавить значение в enum?
От: Turyst  
Дата: 18.06.10 20:26
Оценка:
Здравствуйте, Korchy, Вы писали:

K>моя задача состоит в том, чтобы реализовать удобное управление объектами. Каждый объект описывается классом. Например класс автомобиля Car, человека Human. Каждый из них может выполнять разные действия. Машина — двигаться вперед и назад, человек тоже двигаться и прыгать. Действия могут комбинироваться (прыжок + движение вперед). Чтобы это реализовать мне пришло в голову только сделать массив действий vector в который я заношу что список действий. В программе я каждую секунду пробегаю этот список и проверяю, какие действия там есть и еще не завершились и через case их обрабатываю.

K>for(std:vector<Action*>:iterator i;begin;end)
K>switch case *i->id = run...

K>действия я поименовал через enum просто для наглядности. Мне хотелось сделать некий перечень действий, в который я в каждом классе мог бы добавлять новые действия (как прыжки для человека) и переопределив функцию-обработчик добавить в нее новый case для обработки нового действия. enum же я попытался использовать чтобы хотя бы внутри класса не думать о том, что 1 — это прыжок, а 455 — "тройной тулуп" и т.д.


Про define и другие варианты тут уже рассказали.
Еще вариант. Держать все возможные движения в одном enum. Каждый объект обрабатывает только те события, которые он умеет обрабатывать.
Re[4]: как добавить значение в enum?
От: Turyst  
Дата: 18.06.10 20:31
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>ну вот что мне видится: ты имеешь набор разрозненных объектов объединять которые в единую иерархию нет никогого смысла ибо и свойства и действия у них оч разные.


Я бы не был таким категоричным. Потом например появится легковая машина, грузовая и танк, которые будут уметь обрабатывать одинаковые события типа вперед, назад, стой, и поворот на столько то градусов.
Re[4]: как добавить значение в enum?
От: Turyst  
Дата: 18.06.10 20:36
Оценка:
Здравствуйте, Turyst, Вы писали:

T>Здравствуйте, Korchy, Вы писали:


K>>моя задача состоит в том, чтобы реализовать удобное управление объектами. Каждый объект описывается классом. Например класс автомобиля Car, человека Human. Каждый из них может выполнять разные действия. Машина — двигаться вперед и назад, человек тоже двигаться и прыгать. Действия могут комбинироваться (прыжок + движение вперед). Чтобы это реализовать мне пришло в голову только сделать массив действий vector в который я заношу что список действий. В программе я каждую секунду пробегаю этот список и проверяю, какие действия там есть и еще не завершились и через case их обрабатываю.

K>>for(std:vector<Action*>:iterator i;begin;end)
K>>switch case *i->id = run...

K>>действия я поименовал через enum просто для наглядности. Мне хотелось сделать некий перечень действий, в который я в каждом классе мог бы добавлять новые действия (как прыжки для человека) и переопределив функцию-обработчик добавить в нее новый case для обработки нового действия. enum же я попытался использовать чтобы хотя бы внутри класса не думать о том, что 1 — это прыжок, а 455 — "тройной тулуп" и т.д.


T>Про define и другие варианты тут уже рассказали.

T>Еще вариант. Держать все возможные движения в одном enum. Каждый объект обрабатывает только те события, которые он умеет обрабатывать.
Тоесть не делать enum членом класса.
Re[5]: как добавить значение в enum?
От: zaufi Земля  
Дата: 18.06.10 20:37
Оценка:
Здравствуйте, Turyst, Вы писали:

T>Здравствуйте, zaufi, Вы писали:


Z>>ну вот что мне видится: ты имеешь набор разрозненных объектов объединять которые в единую иерархию нет никогого смысла ибо и свойства и действия у них оч разные.


T>Я бы не был таким категоричным. Потом например появится легковая машина, грузовая и танк, которые будут уметь обрабатывать одинаковые события типа вперед, назад, стой, и поворот на столько то градусов.

не будем забегать вперед
из того что сказал топикстартер этого вовсе не следует. а даже если и появится то грузовики с танками и машинами врядли окажутся в одной иерархии с человеком (и возможно животными, растениями, планетами или там субатомными частицами)
Re[2]: как добавить значение в enum?
От: Сергей Мухин Россия  
Дата: 18.06.10 22:27
Оценка:
Здравствуйте, dilmah, Вы писали:



D>по стандарту, размер энума (сколько бит на него выделить) определяется при определении. То есть компилятор имеет право выделить, скажем, 8 бит, если исходно все элементы в них укладываются. Соответственно в дальнейшем это ограничение не преодолеть.


ну причем тут биты? в вопросе два енума или три
---
С уважением,
Сергей Мухин
Re[4]: как добавить значение в enum?
От: Korchy  
Дата: 19.06.10 04:35
Оценка:
Идею понял, спасибо.
А без буста как такое реализовать?

оверквотинг и топпостинг — deleted. — Кодт
Re[5]: как добавить значение в enum?
От: Korchy  
Дата: 19.06.10 05:37
Оценка:
Да, эта мысль приходила мне в голову. Но я надеялся, что есть способ, которого я не знаю
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.