как добавить значение в 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
Оценка:
Да, эта мысль приходила мне в голову. Но я надеялся, что есть способ, которого я не знаю
Re[5]: как добавить значение в enum?
От: Korchy  
Дата: 19.06.10 05:50
Оценка:
Нет, не получается
Попробовал через указатели на функции все это реализовать, но функции обрабатывающие разные действия имеют разные параметры (чтобы отслеживать окончание действия). Привести их все к одному виду func(void) не получается

оверквотинг и топпостинг — deleted. — Кодт
Re[2]: как добавить значение в enum?
От: alexander_st Россия  
Дата: 19.06.10 11:42
Оценка: 1 (1)
Здравствуйте, Sni4ok, Вы писали:

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


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


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


S>
S>class1 {
S>public:
S>static const int stay = 0;
S>static const int run = 1;
S>};
S>class2:public class1 {
S>public:
S>static const int jump = 2;
S>};
S>

ужас! это каждй кто наследует от таких классов должен будет просмотреть всю иерархию, дабы найти какеи константы есть уже?
но в енумами проблема таже самая будет
тут беда не в енумах а в архитектуре проекта
Re[6]: как добавить значение в enum?
От: zaufi Земля  
Дата: 19.06.10 12:45
Оценка:
Здравствуйте, Korchy, Вы писали:

K>Нет, не получается

K>Попробовал через указатели на функции все это реализовать, но функции обрабатывающие разные действия имеют разные параметры (чтобы отслеживать окончание действия). Привести их все к одному виду func(void) не получается

ну в контейнере должные лежать nullary functors (ну это допустим легко устроить используя рантаймный полиморфизм)
фича в том что то что там буит лежать должно уже иметь в себе связанные параметры, т.е. на момент push_back все параметры уже известны и сохранены вв наследниках полиморфной базы до момента вызова... засада в том что нужно иметь несколько специализаций (под разное число параметров) некой функции, которая буит возвращать nullary functor (наследник нашей базы) (c уже связанными параметрами). в принципе такое бустерным препроцессором делается на раз два ну или руками копипакостничается еси у тя 1-2-3 параметра в твои методы -- собсна это как устроен boost::bind внутри (ну +\- так) -- твоя задача переизобреати валасипед (не боясь при этом квадраатных колес которые неизбежно у тебя получатся)... ну или ждать С++0х
Re[7]: как добавить значение в enum?
От: Korchy  
Дата: 19.06.10 18:10
Оценка: -1 :)))
Да, получается что-то монструозное. Буст мне не хотелось бы использовать т.к. программа ограничена по скорости выполнения, а буст славится своей медленностью. В итоге, лучше обойдусь простыми дефайнами.
Re[3]: как добавить значение в enum?
От: Korchy  
Дата: 19.06.10 18:12
Оценка:
Вполне возможно, что беда именно в архитектуре. Задачу я описал в посте http://www.rsdn.ru/forum/cpp/3849092.1.aspx
Автор: Korchy
Дата: 18.06.10
Как бы вы (хотя бы в общих чертах) порекомендовали ее реализовывать?
Re[4]: как добавить значение в enum?
От: alexander_st Россия  
Дата: 19.06.10 20:21
Оценка:
Здравствуйте, Korchy, Вы писали:

K>Вполне возможно, что беда именно в архитектуре. Задачу я описал в посте http://www.rsdn.ru/forum/cpp/3849092.1.aspx
Автор: Korchy
Дата: 18.06.10
Как бы вы (хотя бы в общих чертах) порекомендовали ее реализовывать?

вариантов много, то точно не стал бы делать человека и танк производными от одного класса... движение человека и движение танка это не одно и то же
в принципе действия должны описываться методами, а не одним методом и параметром что это за действие..
а дальше не понятно зачем в цикле что то проверяется, если узнать что объект свободен или что то делает, то и нужен именно такой метод в базовом классе, если что б выполнялось само действие, то нуден метод Do() в базовом классе, а в объектах хранить что конкретно они должны делать, то биш вызвывая метод eat() у тигра, он в свой стек команд помещает что должен кушать а в методе do() он из стека знает что ему делать...
но это все так, задача то не ясна
Re[2]: как добавить значение в enum?
От: merk Россия  
Дата: 19.06.10 21:43
Оценка:
Здравствуйте, dilmah, Вы писали:

Вообще перечисление — не класс и его "расширять" нельзя.
B C++ enum интерпретируется просто как константы определенные в данной области видимости.
таким образом элементы вашего енума — константы внутри данного класса.
естественно, что в другом классе нельзя написать нечто, что определит новые константы внутри старого класса.
строго говоря, чтобы такое реализовать, пришлось бы устраивать динамические проверки типа енума, чтобы внутри кода работающего с актуальным — расширенным енумомм, можно было использовать дополнительные значения, а вне его — нельзя. но енум — скалярный тип, и у него нет способа определить актуальный тип. тип всегда строго тот, как его поисали при декларации.
для того чтобы расширять типы, нужно делать навороты в виде классов.

если говорить более теоретически, при расширении перечисления например так
формальный синтаксис
enum A {One, Two};
enum B {enum A, Three}; //то есть построили тип как совокупность из старого енума и нового значения
обьект типа B несовместим с обектом типа A.
то есть присваивание обьекту типа А значения B некорректно. Ибо обьект типа А в таком случае может иметь значение Three, которое для него никак не определено. проверка корректности значения типа A будет показывать нарушение опрделения данного типа — что у него могут быть только значения One или Two.

пишите просто константы, а тип сделайте как какой-нить int.
либо в базовом классе пишите все возвожные варианты енума сразу.
Re[5]: как добавить значение в enum?
От: Caracrist https://1pwd.org/
Дата: 20.06.10 08:37
Оценка:
Здравствуйте, Korchy, Вы писали:

K>Идею понял, спасибо.

K>А без буста как такое реализовать?

#include <iostream>
#include <vector>

namespace Action{template<typename AT> void act(void * obj);};
#define CreateAction(ActionName) \
    namespace Action\
    {\
        struct ActionName { virtual void do_##ActionName() = 0; };\
        template<> void act<ActionName>(void * obj)\
        {((ActionName*)obj)->do_##ActionName();}\
    }
CreateAction(jump);
CreateAction(eat);
CreateAction(shit);
CreateAction(stop);
CreateAction(start);
CreateAction(bark);

struct car : Action::start, Action::stop
{
    void do_start() { std::cout << __FUNCTION__ << std::endl; }
    void do_stop() { std::cout << __FUNCTION__ << std::endl; }
};
struct human : Action::eat, Action::shit
{
    void do_eat() { std::cout << __FUNCTION__ << std::endl; }
    void do_shit() { std::cout << __FUNCTION__ << std::endl; }
};
struct tiger : Action::jump, Action::eat
{
    void do_jump() { std::cout << __FUNCTION__ << std::endl; }
    void do_eat() { std::cout << __FUNCTION__ << std::endl; }
};


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

    typedef std::vector<std::pair<void(*)(void*), void*> > actions;
    actions a;
    a.push_back(std::make_pair(Action::act<Action::start>, &c));
    a.push_back(std::make_pair(Action::act<Action::eat>, &h));
    a.push_back(std::make_pair(Action::act<Action::jump>, &t));
    a.push_back(std::make_pair(Action::act<Action::shit>, &h));
    a.push_back(std::make_pair(Action::act<Action::stop>, &c));
    a.push_back(std::make_pair(Action::act<Action::eat>, &t));
    for (actions::iterator it = a.begin(), end = a.end(); it != end; ++it)
    {
        it->first(it->second);
    }
}
~~~~~
~lol~~
~~~ Single Password Solution
Re[3]: как добавить значение в enum?
От: Vain Россия google.ru
Дата: 20.06.10 15:24
Оценка:
Здравствуйте, Korchy, Вы писали:

K>В этом случае class2::Action не будет иметь значений stay и run, а только jump=2 и sit=3. Мне же нужно чтобы в class2::Action были все четыре значения.

Используйте везде int в качестве принимающего, тогда такой проблемы не будет.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re: как добавить значение в enum?
От: Тролль зеленый и толстый  
Дата: 20.06.10 21:20
Оценка:
K>когда я наследую от него другой класс, объект которого должен выполнять еще одно действие (допустим, прыгать), как мне добавить его в список enum?

Лучше всего никак. Попытка делать подобное возникает из-за логической ошибки. Это как бы "вывернутый полиморфизм". На самом деле, наследование енума и смысла-то не имеет: базовый класс может обрабатывать только свои константы, а в производном имеет смысл обрабатывать только новые константы, таким образом наследование просто бессмысленно.

Тебе необходимо выделить общие свойства всех объектов, обозначаемых перечислением.

Короче, пересмотри решение.
Re[4]: как добавить значение в enum?
От: Head Ache  
Дата: 21.06.10 04:50
Оценка: 1 (1) -1
Здравствуйте, zaufi, Вы писали:

Z>struct car

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

Разве здесь уместен статический полиморфизм?
имхо классический шаблон стратегия

class Action
{}

class ActionRun: public Action
{}

class Actor
{
virtual void Start(Action& a)=0;
virtual void Stop(Action& a)=0;
}

class Creature: public Actor
{
virtual void Run(ActionRun& a);
virtual void Start(Action& a);
virtual void Stop(Action& a);
}

примерно так — т.е. вместо enum виртуальный тип с произвольными параметрами, с некоторым интерфейсом.
Просто enum соответсвует тип с единственным int параметром. Что не мешает при необходимости его расширить.
Этот аккаунт покинут.
Re[5]: как добавить значение в enum?
От: Korchy  
Дата: 21.06.10 08:04
Оценка:
Спасибо, наверное, это самый лучший путь, представить каждое действие отдельным интерфейсным классом. В этом направлении и буду двигаться.
Re[3]: как добавить значение в enum?
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 21.06.10 12:17
Оценка:
Здравствуйте, 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 — "тройной тулуп" и т.д.

Ты не правильно решаешь проблему. На мой взгляд тут будет уместен паттёрн Посетитель (хотя, если иерархия объектов, над которыми выполняются действия не стабилен и очень часто меняется, то надо думать)
Как минимум, можно однозначно выделить 2 иерархии классов: action и item оба они абстракнтые, от них наследовать классы действий и классы объектов действий.
Sic luceat lux!
Re[5]: как добавить значение в enum?
От: zaufi Земля  
Дата: 21.06.10 13:11
Оценка:
Здравствуйте, Head Ache, Вы писали:

HA>Разве здесь уместен статический полиморфизм?

мы (ну те из нас кто не телепат) не знаем что здесь уместнее ... аффтар не ракрывает деталей использования
я просто предложил вариант со своими плюсами и минусами... аффтар выберет то что по его мнению ему больше подходит
Re[5]: как добавить значение в enum?
От: Korchy  
Дата: 21.06.10 14:15
Оценка:
Вопрос в продолжение использования такого подхода:
у меня есть список действий std::vector<Action*> Actions
в нем хранятся действия, которые выполняются на данный момент
Каким образом мне найти нужное действие в списке, чтобы, допустим, его удалить (прекратить выполнять)? Через dynamic_cast проверять на соответсвие нужному типу (Action или ActionRun)? dynamic_cast достаточно долгий при длинных ветвях наследований, поэтому не хотелось бы его использовать. Или можно как-то еще?
Re[6]: как добавить значение в enum?
От: Head Ache  
Дата: 21.06.10 23:19
Оценка:
Здравствуйте, Korchy, Вы писали:

K>Вопрос в продолжение использования такого подхода:

K>у меня есть список действий std::vector<Action*> Actions

1. Использовать vector< shared_ptr<Action> >. Почему так — читать "effective stl".

K>в нем хранятся действия, которые выполняются на данный момент

K>Каким образом мне найти нужное действие в списке, чтобы, допустим, его удалить (прекратить выполнять)? Через dynamic_cast проверять на соответсвие нужному типу (Action или ActionRun)? dynamic_cast достаточно долгий при длинных ветвях наследований, поэтому не хотелось бы его использовать. Или можно как-то еще?

2. Это опять частный случай: действительно ли тип элемента — единственный критерий и всегда им будет?
Изучить ситуацию при которой необходимо удаление. Добавить в базовый класс виртуальную функцию вроде bool CheckDelete() или OnActivate() и т.п. Обработать в производных классах.
А может, лучше это будет невиртуальная функция, проверяющая переменную в базовом классе. Которая в производных классах когда-то меняется.
Для удаления сделать предикат, проверяющий эту функцию.
Этот аккаунт покинут.
Re[7]: вдогонку
От: Head Ache  
Дата: 22.06.10 00:05
Оценка:
Здравствуйте, Head Ache, Вы писали:

HA>1. Использовать vector< shared_ptr<Action> >. Почему так — читать "effective stl".


Это если vector управляет объектами, ну я то не знаю, откуда указатели.
Этот аккаунт покинут.
Re[6]: как добавить значение в enum?
От: Erop Россия  
Дата: 22.06.10 06:36
Оценка:
Здравствуйте, Korchy, Вы писали:

K>Вопрос в продолжение использования такого подхода:

K>у меня есть список действий std::vector<Action*> Actions
K>в нем хранятся действия, которые выполняются на данный момент
K>Каким образом мне найти нужное действие в списке,..

Зависит от того как именно и что именно ты делаешь.
Если, например, члены той иерархии, что у тебя была изначально, растут из IItem, а IAction выглядит как-то так:
class IAction {
protected:
    virtual ~IAction() {}
public:
    virtual Do( IItem* ) const = 0;
}
то действия сами являются ID себя. Нопример можно использовать IAction* в качестве ID...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.