Подскажите, пожалуйста, есть класс, объект которого может выполнять 2 действия (стоять и бежать), названия которых я указываю в перечислении
class1 {
public:
enum Action {stay,run};
}
когда я наследую от него другой класс, объект которого должен выполнять еще одно действие (допустим, прыгать), как мне добавить его в список enum? Только переопределяя перечисление заново?
Или можно по другому как-то? А если классов-наследников много, stay и run должны копироваться в каждый? Или здесь вообще enum не к месту и нужно использовать что-то другое?
K>Или можно по другому как-то? А если классов-наследников много, stay и run должны копироваться в каждый? Или здесь вообще enum не к месту и нужно использовать что-то другое?
по стандарту, размер энума (сколько бит на него выделить) определяется при определении. То есть компилятор имеет право выделить, скажем, 8 бит, если исходно все элементы в них укладываются. Соответственно в дальнейшем это ограничение не преодолеть.
я не оч понимаю зачем этим объектам 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_<> если хочется какогото числового значения...
ну а в целом чтобы полноценно рассказать о других способах надо знать чего ты хочешььь сделать...
Здравствуйте, 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.]
[Даю очевидные ответы на риторические вопросы]
моя задача состоит в том, чтобы реализовать удобное управление объектами. Каждый объект описывается классом. Например класс автомобиля Car, человека Human. Каждый из них может выполнять разные действия. Машина — двигаться вперед и назад, человек тоже двигаться и прыгать. Действия могут комбинироваться (прыжок + движение вперед). Чтобы это реализовать мне пришло в голову только сделать массив действий vector в который я заношу что список действий. В программе я каждую секунду пробегаю этот список и проверяю, какие действия там есть и еще не завершились и через case их обрабатываю.
for(std:vector<Action*>:iterator i;begin;end)
switch case *i->id = run...
действия я поименовал через enum просто для наглядности. Мне хотелось сделать некий перечень действий, в который я в каждом классе мог бы добавлять новые действия (как прыжки для человека) и переопределив функцию-обработчик добавить в нее новый case для обработки нового действия. enum же я попытался использовать чтобы хотя бы внутри класса не думать о том, что 1 — это прыжок, а 455 — "тройной тулуп" и т.д.
В этом случае class2::Action не будет иметь значений stay и run, а только jump=2 и sit=3. Мне же нужно чтобы в class2::Action были все четыре значения.
В классе-наследнике, если не ошибаюсь, снова будет выполнена операция определения размера и будет выделено столько памяти, сколько нужно. Проблема в том, что для этого enum нужно копировать целиком из класса-предка и добавлять значения в него. Получается жуткое дублирование кода и путаница, как следствие. Мне хотелось этого избежать.
Здравствуйте, Korchy, Вы писали:
K>Подскажите, пожалуйста, есть класс, объект которого может выполнять 2 действия (стоять и бежать), названия которых я указываю в перечислении K>
K>когда я наследую от него другой класс, объект которого должен выполнять еще одно действие (допустим, прыгать), как мне добавить его в список enum? Только переопределяя перечисление заново? 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;
};
Здравствуйте, 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 — "тройной тулуп" и т.д.
ну вот что мне видится: ты имеешь набор разрозненных объектов объединять которые в единую иерархию нет никогого смысла ибо и свойства и действия у них оч разные. одно из решений на вскидку:
просто заводим контейнер с действиями которые дребуется выполнять и bindим в него объекты и методы. если приспичит можно писать более сложные функторы кторые будут действовать над несколькими объектами одновременно или выполнять несколько действий над одним (ну типа бежать и прыгать) -- как захочется в общем...
таким образом никакие енумы нафиг не нужны и соответсна не придется их синхронизировать а также не нада буит постоянно модифицировать switch втыкая в него реакцию на новые действия и вообще от самих объектов ничего не требуется (ну разве что наличие экземпляра)
Здравствуйте, 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. Каждый объект обрабатывает только те события, которые он умеет обрабатывать.
Здравствуйте, zaufi, Вы писали:
Z>ну вот что мне видится: ты имеешь набор разрозненных объектов объединять которые в единую иерархию нет никогого смысла ибо и свойства и действия у них оч разные.
Я бы не был таким категоричным. Потом например появится легковая машина, грузовая и танк, которые будут уметь обрабатывать одинаковые события типа вперед, назад, стой, и поворот на столько то градусов.
Здравствуйте, 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 членом класса.
Здравствуйте, Turyst, Вы писали:
T>Здравствуйте, zaufi, Вы писали:
Z>>ну вот что мне видится: ты имеешь набор разрозненных объектов объединять которые в единую иерархию нет никогого смысла ибо и свойства и действия у них оч разные.
T>Я бы не был таким категоричным. Потом например появится легковая машина, грузовая и танк, которые будут уметь обрабатывать одинаковые события типа вперед, назад, стой, и поворот на столько то градусов.
не будем забегать вперед
из того что сказал топикстартер этого вовсе не следует. а даже если и появится то грузовики с танками и машинами врядли окажутся в одной иерархии с человеком (и возможно животными, растениями, планетами или там субатомными частицами)
D>по стандарту, размер энума (сколько бит на него выделить) определяется при определении. То есть компилятор имеет право выделить, скажем, 8 бит, если исходно все элементы в них укладываются. Соответственно в дальнейшем это ограничение не преодолеть.