Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вопрос по организации ООП структуры программы. 
:(
    Опции темы
KPEHDEL
Дата 31.7.2012, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Здраствуйте, написал класс Button обрабатывающий действия с кнопокой, наведение мыши на неё, нажатие, отжатие...

Информация:
Есть метод объявления данных кнопки, x, y, w, h, сурфейса, координат спрайтов.
data( int x, int y, int w, int h, SDL_Surface *Surface, SDL_Rect* sprite );
        
Есть метод обработки нажатия кнопки mouse_button_down().

В этом методе при нажатии кнопки, должен вызываться метод с названием кнопки из класса Event_Button. Например если обрабатывается объект-кнопка Button_Header_Menu_Enter то имя метода из класса Event_Button будет равно имени объекта.

Класс Event_Button содержит объект Button_Down и публичные методы имеющие название кнопок.
И в методе mouse_button_down() о котором я писал выше, вызывается например так:
Button_Event.название_метода();

Вопрос:
Как правильно в соответствии с ООП передать название метода, чтобы при нажатии на определённую кнопку вызывался метод с её именем из класса Button_Event, или как это вообще делается?
На C++, никогда не писал, ранее писал на C. Теперь встал на путь C++. 
Поэтому не всегда мне ясно как правильнее сделать в соответствии с ООП. Буду благодарен если направите мои мысли в нужное русло.

С нетерпением жду ответа, заранее спасибо.
PM MAIL WWW ICQ   Вверх
bsa
Дата 31.7.2012, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Почитай: http://qt-project.org/doc/qt-4.8/gettingstarted-develop.html
Это введение в библиотеку Qt. Она написана довольно хорошим стилем и ее архитектура может быть использована как пример. Система сигналов/слотов, правда, там не самая удачная. Поэтому, в своем дизайне можешь использовать boost::signals.
PM   Вверх
baldina
Дата 31.7.2012, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Имена методов/классов/переменных в C++ недоступны в runtime (и вообще поддержка RTTI совсем небольшая), так что идентифицировать по имени без специальных бубнов не получится. Но и не надо: каждая кнопка сама знает, какой событие должно сгенерироваться, и просто вызывает соответствующий метод:

Код

class Event_Button {
  public:
    void Open ();
    void Save ();
    void Close ();
};

class Button {
  protected:
    Event_Button& e;
  public:
    Button (Event_Button& e) : e(e) {}
    virtual void mouse_button_down () = 0;
};

class OpenButton {
  public:
    OpenButton (Event_Button& e) : Button(e) {}
    virtual void mouse_button_down ()  {
       e.Open ();
    }
};

class SaveButton {
  public:
    SaveButton (Event_Button& e) : Button(e) {}
    virtual void mouse_button_down ()  {
       e.Save ();
    }
};
class CloseButton {
  public:
    CloseButton (Event_Button& e) : Button(e) {}
    virtual void mouse_button_down ()  {
       e.Close ();
    }
};


Добавлено @ 17:42
а вот если мы хотим связать произвольную кнопку с произвольным событием, потребуется какой-то механизм связывания. та самая система слотов/сигналов.

Это сообщение отредактировал(а) baldina - 31.7.2012, 17:44
PM MAIL   Вверх
baldina
Дата 31.7.2012, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



в простейшем виде вот так примерно
http://codepad.org/zNow66oD
PM MAIL   Вверх
KPEHDEL
Дата 31.7.2012, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Спасибо, всем ответившим. Направление в котором идти уловил. Буду читать, думать, позже отпишусь о результатах и о том, как сделал.

Это сообщение отредактировал(а) KPEHDEL - 31.7.2012, 18:05
PM MAIL WWW ICQ   Вверх
Result
Дата 31.7.2012, 21:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 52
Регистрация: 15.5.2011

Репутация: 2
Всего: 5



Цитата(baldina @ 31.7.2012,  17:40)
Код

class Event_Button {
  public:
    void Open ();
    void Save ();
    void Close ();
};

class Button {
  protected:
    Event_Button& e;
  public:
    Button (Event_Button& e) : e(e) {}
    virtual void mouse_button_down () = 0;
};

class OpenButton {
  public:
    OpenButton (Event_Button& e) : Button(e) {}
    virtual void mouse_button_down ()  {
       e.Open ();
    }
};

class SaveButton {
  public:
    SaveButton (Event_Button& e) : Button(e) {}
    virtual void mouse_button_down ()  {
       e.Save ();
    }
};
class CloseButton {
  public:
    CloseButton (Event_Button& e) : Button(e) {}
    virtual void mouse_button_down ()  {
       e.Close ();
    }
};

Кажется забыли дописать паблик наследование.
PM   Вверх
baldina
Дата 1.8.2012, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(Result @  31.7.2012,  21:19 Найти цитируемый пост)
Кажется забыли дописать паблик наследование. 

да, забыли
PM MAIL   Вверх
KPEHDEL
Дата 2.8.2012, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Выбор мой пал всё же не на boost, а на старый добрый Указатель на член. Подходит под задачу и подключать ничего не надо. Но boost::signals скоро тоже понадобится.

Продолжу тему своими следущими вопросами, подходящими под оглавление темы.

1.
Информация:
Я использую конструктор/деструктор, но также когда требуется создаю метод init() в котором вызывается, то, что должно быть вызвано единажды, а не для каждого объекта.
Например:
SDL_EnableUNICODE( SDL_ENABLE ); - если вызывать в конструкторе, то после второго вызова для второго объекта, вернёт ошибку. Такое вызываю в методе init().

В конструкторе исключительно то, что требуется инициализировать для каждого объекта.

Вопрос:
Это нормально? Принято ли так делать в C++ или лучше использовать только конструктор?

2.
Информация:
Есть объекты класса с конструктором принмающим параметры.
Требуется объявить один объект, для которого параметры не нужны. По причине, что через этот объект нужно вызывать просто какой-то метод в методе другого класса.
Пример:
Где-то вызывается Button.Header_Menu();
А в Header_Menu() вызываются все остальные "нормальные" объекты с параметрами конструктора.
Поэтому, объекту проводнику параметры не нужны.

Вопрос:
В таком случаи делать Button Button( NULL, NULL, NULL, NULL, NULL, NULL, NULL );
или есть другие способы?

3.
Информация:

Есть конструктор принимающий параметр SDL_Surface* source и объект передающий его.
В конструкторе данный параметр присваивается члену класса ClassName::source = source;

Есть метод который используя данный член класса должен выводить сурфейс на экран.
Например такой:
Код

void ClassName::show() {
    surface.apply_surface( img_x, img_y, source );    
}


Однако сурфейс не выводится.
Если же передавать сурфейс в метод вывода(в примере это show), там его присвоить члену и попробовать вывести, то сурфейс выведиться на экран
Например так:
Код

void StringInput::show( SDL_Surface* s ) {
    source = s;
    surface.apply_surface( img_x, img_y, source );
}


Вопрос:
Подскажите в чём может быть причина?

Если требуется больше информации, спрашивайте.

С нетерпением жду ответа.
Заранее спасибо.

Это сообщение отредактировал(а) KPEHDEL - 2.8.2012, 23:19
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 2.8.2012, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(KPEHDEL @  2.8.2012,  22:13 Найти цитируемый пост)
SDL_EnableUNICODE( SDL_ENABLE ); - если вызывать в конструкторе, то после второго вызова для второго объекта

эта функция не имеет ассоциации с объектом. ее бессмысленно вызывать дважды, разве чтоб: SDL_EnableUNICODE(0/1)

Цитата(KPEHDEL @  2.8.2012,  22:13 Найти цитируемый пост)
2.
Информация:
Есть объекты класса с конструктором принмающим параметры.
Требуется объявить один объект, для которого параметры не нужны. По причине, что через этот объект нужно вызывать просто какой-то метод в методе другого класса.
Пример:
Где-то вызывается Button.Header_Menu();
А в Header_Menu() вызываются все остальные "нормальные" объекты с параметрами конструктора.
Поэтому, объекту проводнику параметры не нужны.

Вопрос:
В таком случаи делать Button Button( NULL, NULL, NULL, NULL, NULL, NULL, NULL );
или есть другие способы?

не понял о чем речь...

Цитата(KPEHDEL @  2.8.2012,  22:13 Найти цитируемый пост)
Есть метод который используя данный член класса должен выводить сурфейс на экран.
Например такой:
void ClassName::show() {
    surface.apply_surface( img_x, img_y, source );    
}

Однако сурфейс не выводиться.

покажи конструктор.

PM WWW   Вверх
bsa
Дата 2.8.2012, 22:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(KPEHDEL @  2.8.2012,  23:13 Найти цитируемый пост)
Выбор мой пал всё же не на boost, а на старый добрый Указатель на член. Подходит под задачу и подключать ничего не надо.
я тебе очень сочувствую. ты собрался использовать тот самый костыль, которой существует в языке по ошибке (не додумали разработчики). В итоге, использовать его будет крайне проблематично. Уж поверь. Особенно, когда появится разнообразие классов.
PM   Вверх
KPEHDEL
Дата 2.8.2012, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 31.3.2010

Репутация: нет
Всего: нет



Цитата

эта функция не имеет ассоциации с объектом. ее бессмысленно вызывать дважды, разве чтоб: SDL_EnableUNICODE(0/1)

Я о том и писал, в общем я понял, что использовать метод init() и конструктор вместе это нормально...

Цитата

не понял о чем речь...

Речь о том, нормально ли так объявлять объекты, которые, в отличии от других объектов этого же класса не должны иметь параметров.

Цитата

покажи конструктор.

Код

StringInput::StringInput( int x_img, int y_img, int x_text, int y_text, int w_text, int h_text, SDL_Surface* source ) {
    //Координаты текста в поле ввода.
    text_box.x = x_text;
    text_box.y = y_text;
    text_box.w = w_text;
    text_box.h = h_text;
    
    //Координаты изображения поля ввода.
    StringInput::img_x = x_img;
    StringInput::img_y = y_img;
    StringInput::source = source;
                                        
    //Initialize the string
    str = "";

    //Free text surface
    SDL_FreeSurface( input_text );
}



bsa, пока ничего серьёздного, позже думаю обстоятельства сами заставят перейти на boost::signals, хотя наверное лучше сразу...

Это сообщение отредактировал(а) KPEHDEL - 2.8.2012, 23:17
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 2.8.2012, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(KPEHDEL @  2.8.2012,  23:11 Найти цитируемый пост)
StringInput::source = source;

после этой строки добавь:
Код

std::cout << StringInput::source << std::endl;

и в методе StringInput::show() тоже добавь вывод:
Код

std::cout << StringInput::source << std::endl;

ну и сравни значение полученное в конструкторе с тем, что получаешь в StringInput::show().

Цитата(KPEHDEL @  2.8.2012,  23:11 Найти цитируемый пост)
нормально ли так объявлять объекты

показывай кодом. все равно не понимаю.

PM WWW   Вверх
Result
Дата 3.8.2012, 08:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 52
Регистрация: 15.5.2011

Репутация: 2
Всего: 5



Цитата(KPEHDEL @ 2.8.2012,  22:13)
2.
Информация:
Есть объекты класса с конструктором принмающим параметры.
Требуется объявить один объект, для которого параметры не нужны. По причине, что через этот объект нужно вызывать просто какой-то метод в методе другого класса.
Пример:
Где-то вызывается Button.Header_Menu();
А в Header_Menu() вызываются все остальные "нормальные" объекты с параметрами конструктора.
Поэтому, объекту проводнику параметры не нужны.

Вопрос:
В таком случаи делать Button Button( NULL, NULL, NULL, NULL, NULL, NULL, NULL );
или есть другие способы?

Можно добавить еще один конструктор т.н. конструктор по умолчанию :
Код

//*.h
struct Button{
    Button();
    Button(T* arg1, Y* arg2);
    
};

//*.cpp
Button::Button(T* arg1, Y* arg2){/**/}

Button::Button(){/**/}


PM   Вверх
borisbn
Дата 3.8.2012, 08:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(KPEHDEL @  2.8.2012,  22:13 Найти цитируемый пост)
Я использую конструктор/деструктор, но также когда требуется создаю метод init() в котором вызывается, то, что должно быть вызвано единажды, а не для каждого объекта.

зачем тогда init - метод этого класса ? Если нужно вызвать что-то один раз сделай так
Код
MyClass::MyClass()
{
    static bool /*или что она там возвращает*/ res = SDL_EnableUNICODE( SDL_ENABLE );
}



Это сообщение отредактировал(а) borisbn - 3.8.2012, 13:48


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
bsa
Дата 3.8.2012, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(KPEHDEL @  3.8.2012,  00:11 Найти цитируемый пост)
позже думаю обстоятельства сами заставят перейти на boost::signals, хотя наверное лучше сразу...
поверь мне, когда доходит до "обстоятельства сами заставят", то будешь биться головой об стенку, так как поменять сотни-тысячи строк в нескольких десятках файлов - удовольствие не для каждого.
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0631 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.