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...
Пока на собственное сообщение не было ответов, его можно удалить.