Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Реализация callback вызова метода класса (делегат) |
Автор: Ravenan 24.5.2006, 12:04 |
Всем доброе время суток. Последние пару лет писал на C#, а тут пришлось на С++ вернуться. Не могу реализовать довольно простую как мне кажется вешь, просто не верится что это не выполнимо ![]() ЗЫ Имеется ввиду не передавая в класс B указатель на класс А |
Автор: Mayk 24.5.2006, 14:47 | ||
Придется. Но можно замаскировать. Ну например вот так:
(comeau скомпилировал) То есть мы делаем класс каллбэк, а он сам решает что и кому ему передать управление - ф-ции-члену класса, вызвать какую либо обычную ф-цию или ещё что. ps. кстати, этот вопрос всплывает не в первый раз. на моей памяти во второй. это не укор автору темы, это небольшая статистика ![]() |
Автор: Ravenan 24.5.2006, 15:42 |
Mayk, Большое спасибо ![]() |
Автор: Earnest 24.5.2006, 15:48 |
В С++ делегатов нет. Пока. Но можно воспользоваться boost::function - это очень гибкий механизм, который наверняка войдет в следующую реинкарнацию STL. Это примерно то же самое, что написал Mayk, но гораздо мощнее - любые параметры, любые возвр. значения и т.д. |
Автор: MAKCim 24.5.2006, 16:00 |
см. Александреску - обобщенный функтор тоже любое возвращаемое значение, любые параметры (практически их произвольное количество) он может инкапсулировать обычный функтор, указатель на функцию, указатель на функцию-член имхо, обобщеннее трудно себе представить |
Автор: Ravenan 24.5.2006, 16:09 |
Mayk, Радость омрачилась ошибкой линкера ![]() Error 1 error LNK2001: unresolved external symbol "public: virtual void __thiscall Callback::operator()(void)" (??RCallback@@UAEXXZ) qq.obj компилятор - VS2005 |
Автор: MAKCim 24.5.2006, 18:47 | ||
|
Автор: Ravenan 24.5.2006, 19:08 |
MAKCim, Спасибо, теперь все ок! Вот только думаю раз на такие ухищрения приходится идти - может сама архитектура неправильная? ![]() У меня есть класс который прнимает сообщения с клавиатуры через DirectInput. Я хотел бы дать ему хеш-таблицу с callback методами для разных клавиш. Самой обработкой естественно другой класс заниматься будет. Не подскажите - нормальная вообще практика подобная? То есть это стандартный подход при проектировании или подобных ситуаций в С++ стоит избегать? |
Автор: MAKCim 24.5.2006, 21:21 | ||||||
вполне нормальная сделать что-то типа
и вызывать потом
|
Автор: Ravenan 25.5.2006, 17:15 | ||||
MAKCim, Прошу помощи в решении еще одной возникнувшей проблемы ![]() Все прекрасно работает если метод вызывается непосредственно там куда его передали вроде
А если bc сохранить в каком-то поле класса и вызвать потом из другого метода, то приложение вываливается.
В дебагере видно что хотя сам указатель p не изменился при переходе в другую функцию, значение структуры Callback на которую он указывает самопроизвольно изменилось. Объясните пожалуйста причину подобного побочного еффекта ![]() |
Автор: likehood 25.5.2006, 17:24 | ||
Может у функций все же разные имена? |
Автор: Ravenan 25.5.2006, 17:32 |
baronp, да, сорри, подправил |
Автор: likehood 25.5.2006, 17:36 |
а как ты вызываешь 1-ю функцию? |
Автор: Ravenan 25.5.2006, 17:48 | ||
|
Автор: likehood 25.5.2006, 17:57 |
При вызове foobar в кострукторе A() ты создаешь временный объект, который разрушается после выхода из foobar. Выход: в классе B вместо указателья обявить переменную, но тогда нужен default-конструктор в MemberCallback и там же нужен copy-коструктор. Добавлено @ 18:01 На счет замены указателья это я погорячился. Надо в первый foobar передавать не ссылку, а указатель, при этом объект MemberCallback в конструкторе А придется создавать динамически. Тогда придется думать об удалении этого объекта (возможно auto_ptr). |
Автор: Ravenan 25.5.2006, 18:12 |
baronp, Спасибо, работает! ![]() |
Автор: MAKCim 25.5.2006, 18:14 | ||||
странно что у тебя такое прокатывает
тут создается временный объект, но foobar принимает ссылку на Callback, а по стандарту возможна только константная ссылка на временный объект |
Автор: Ravenan 25.5.2006, 18:34 |
MAKCim, еще раз доказывает что каждый компилятор такое моменты решает как ему угодно а не по стандарту. Все прекрасно работало пока не уничтожался этот временный объект |
Автор: Void 25.5.2006, 18:34 |
MAKCim, одно из нестандартных расширений MSVC (автор, по всей видимости, пользуется именно им). Но таки лучше параметр сделать константной ссылкой и оператор () тоже константным. |
Автор: MAKCim 25.5.2006, 21:07 | ||
имхо, лучше ими не пользоваться ввиду непереносимости в общем случае |
Автор: takedo 26.5.2006, 06:14 | ||
Ravenan,
если пишешь приложение оконное - стопудов неправильная!!! Я также как и ты сперва поизвращался с передачей адреса функции класса - ввсё нормально заработало, но потом ещё раз проанализировав(а информацию я брал в какой-то статье на RSDN, называлась она что-то типа самые быстрые делегаты на C++) я понял, что это неприемлемо для оокнонных приложений, потому как каждый компилятор делает такие вещи по своему(см. статью которую ты ещё не нашел ![]() ![]() Добавлено @ 06:20 Странно, помню, что читал совершенно другую статью, а нашёл сейчас вот эту ![]() http://www.rsdn.ru/article/cpp/delegates.xml |
Автор: Ravenan 26.5.2006, 11:49 |
takedo, http://www.rsdn.ru/article/cpp/delegates.xml - довольно познавательная статья. Прочитай я ее раньше - не напрягал бы всех ![]() Насчет сообщений идея интересная... Приложение у меня игровое, специфика у него следующая: есть основной класс и класс обработки ввода (на DirectInput). Обработку ввода мне показалось логичным вынести в отдельный класс так как ее реализация может менятся. Хотелось бы в классе обработки ввода иметь хеш-таблицу из пар клавиша-обработчик и вызывать обработчики по нажатию. Такой подход мне показался наиболее логичным. Конечно можно реализовать все по другому так что делегаты не понадобятся, но я исхожу из языково-независимого проектирования архитектуры приложения. Думаю что возникшая у меня ситуация не редка и при проектировании бизнес-приложений, потому интересно как обычно решают эту проблему. |
Автор: takedo 29.5.2006, 10:07 |
Ravenan, дело твоё ![]() |