Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Как задать членом класса указатель на функцию? |
Автор: Нитонисе 4.1.2013, 13:37 | ||||
Пишу класс
Этот код конечно не работает, просто что бы пояснить чего я хочу. А хочу я иметь членом класса некую функцию func, реализация которой может быть произвольной. Ну вот например:
Как это сделать? |
Автор: EvilsInterrupt 4.1.2013, 14:55 | ||||
Нитонисе, 1)
Это верно? Если оформить по красивее, то:
2) Почему в setFunc присваиваете в переменную "void *func;", а в DoFunc() дергаете какую-то мифическую f() ? 3) Может Вам изучить понятие "функтор" ? Другие названия этого термина "Объект функции". Это класс с переопределенным оператором "круглые скобки", чтобы объект этого класса вел себя как функция. Т.е. "все что выглядит как функция, ведет себя как функция = есть функция" |
Автор: Нитонисе 4.1.2013, 15:58 |
С оформлением я не заморачивался, потому как писал прямо в форме ответа. Соответственно и опечатку в DoFunc допустил. А вот по п.3 видно надо изучать матчасть. |
Автор: mes 4.1.2013, 18:36 | ||
понятие функция может быть легко расширено до функционального обьекта и это расскрывает новые свободы, о чeм уже было сказано выше.. для ознакомления с подобной концепцией см. [boost:: / (c++11)std::] function и bind.. Добавлено через 2 минуты и 16 секунд
для простой функции никаких наворотов не требуется, всe работает из коробки ) |
Автор: EvilsInterrupt 4.1.2013, 18:42 |
Нитонисе, Поясни какую проблему ты решаешь? Для чего потребовался такой код? Возможно есть решение проще. |
Автор: mes 4.1.2013, 18:42 | ||
вот набросок :
|
Автор: NoviceF 4.1.2013, 20:26 |
![]() |
Автор: EvilsInterrupt 4.1.2013, 20:47 |
NoviceF, По моему никнейму поищи недавнюю тему, которую я создал. В ней про функторы достаточно много рассказано |
Автор: mes 4.1.2013, 23:05 | ||
глянуть хотя бы на стл :
http://liveworkspace.org/code/409lqK$0 Добавлено через 3 минуты и 54 секунды если вместо 10 и 15 поставить переменные, то реализовать подобное через указатели на функции будет затруднительно.. Добавлено через 6 минут и 52 секунды ну а с лямбдой, как дальнейшее развитии функтора, выглядит еще удобнее : http://liveworkspace.org/code/409lqK$2 Добавлено через 9 минут и 31 секунду ну и с замыканием контекста : http://liveworkspace.org/code/409lqK$3 все это приведенно на скорую руку, на самом деле преимущества гораздо шире ) |
Автор: EvilsInterrupt 4.1.2013, 23:22 | ||
mes, Я бы предпочел так оформить код:
Понятней как-то... ) |
Автор: NoviceF 4.1.2013, 23:47 |
Спасибо за примеры, но представление о функторах и лямбдах я имею ![]() |
Автор: EvilsInterrupt 4.1.2013, 23:51 |
NoviceF, Польза от использования функторов в том что это объекты! А объекты имеют состояние. То есть перед подачей объекта куда-либо ты можешь его про инициализировать, а после того как это "куда-либо" отработало ты еще можешь прочитав его состояние знать результат какой-угодно тебе. Рекомендую книгу Джосьютиса "Стандартная библиотека C++". Сам читаю, очень опечален тем что раньше ее не прочитал ((( |
Автор: NoviceF 5.1.2013, 00:05 | ||||
спасибо, учту.
хороших книжек много и читаю я их не быстро ![]() |
Автор: mes 5.1.2013, 04:05 | ||
![]() по данному классу сказать проблематично, так как требования по задаче не сформурлированы, а я увы не телепат ![]()
грубо говоря, да ![]() ![]() |
Автор: EvilsInterrupt 5.1.2013, 10:17 | ||
NoviceF, Забыл сказать о "лямбда". Если Вы помните, что в C++03 нужно писать так:
В случае использования "лямбда", доступных в C++11, когда Вы знаете что ваша_кустом_функция очень маленькая, то Вы можете написать ее код, но без указания ее имени. Это удобно тем что 1) читающий код будет меньше скролить экран в другое место, чтобы увидеть реализацию, т.е. чтение кода будет более эффективным. 2) сокращает набор текста, а программистам же так не нравится много писать |
Автор: mes 5.1.2013, 13:55 | ||||
![]()
почти.. по кол-ву символов выходит также.. программистам не нравится выдумывать имена одноразовых функций )) и еще кое что забыто, из за того что начали сравнивать лямбду с функцией, позабыв про бинд.. самое важное свойство - это замыкание контекста )) ибо локальную функцию (чтоб не скролить) с небольшой избыточностью, можно получить и без лямбды.. |
Автор: NoviceF 5.1.2013, 15:44 | ||||||
это же синтаксис и пример использования обычной функции в алгоритме STL? лямбду я понимаю как нечто
Это для случая:
спасибо Борису (borisbn) ![]() конечно, возможен и вариант использования лямбды в роли предиката. вот об это не слышал, почитал вику, там как пример замыкания приводятся опять таки лямбда функции. Но в целом смысл понятен. Удобно, что лямбда может обращаться к внешним переменным, в том числе и по ссылке. |
Автор: mes 5.1.2013, 17:01 | ||||
лямбда на самом деле нечто большее )) если с замыканием она "анологична" функтору, то без контекста - обычной функции.. и ее легко можно использовать для адаптации сигнатуры :
http://liveworkspace.org/code/4xodmZ$0 Добавлено @ 17:05 то есть, в лямбде сильна не только ее анонимность, а таже ее конвертибельность, при отсутствии (ненужного) оверхеда.. Добавлено @ 17:10 вот еще один примерчик с лямбдами как с-функции:
http://liveworkspace.org/code/3tkd17$0 |
Автор: NoviceF 5.1.2013, 17:12 |
головокружительные пируэты ![]() Добавлено @ 17:15 просветите, что за синтаксис? отбой, нашёл в вики. Надо всётаки когда-нибудь дочитать список "нововведений" в с++11.. где тут смайлик *слоупок*.. |
Автор: mes 5.1.2013, 17:18 |
http://www.cprogramming.com/c++11/c++11-ranged-for-loop.html http://en.cppreference.com/w/cpp/language/range-for |
Автор: NoviceF 5.1.2013, 17:23 | ||
Отличная вещь.. осталось только подружить qnx Momentics с gcc 4.7.. ![]() |
Автор: Нитонисе 9.1.2013, 10:58 | ||||||||
В развитие темы ![]() Я тут попробовал набросать пример по наводке mes. Пишу в RAD Studio Builder XE, но думаю для данной задачи это не принципиально, просто код билдеровский. Вот класс
Вот заголовочный файл формы в билдере
Вот применение моего тестового класса
Ошибка компилятора
Это чего он от меня хочет? ![]() ![]() |
Автор: bsa 9.1.2013, 11:33 |
Нитонисе, во-первых, указатель на метод класса несколько иначе записывается. во-вторых, адрес метода класса берется тоже несколько иначе в-третьих, а какое отношение данный вопрос имеет к обсуждаемой теме? С указателем на функцию в качестве члена класса у тебя проблем нет. |
Автор: Нитонисе 9.1.2013, 12:26 | ||
Такое отношение, что я пока не разобрался как это сделать. Мне нужно в свой класс в разные моменты времени подсовывать разные функции других классов. Вот как в этом простом примере я передаю указатели на функции класса формы. |
Автор: NoviceF 9.1.2013, 12:54 | ||
![]() |
Автор: Нитонисе 9.1.2013, 13:17 | ||
Да, будут. Я делаю класс контролирующий открытие/закрытие/сохранение файла. На форме есть набор компонентов, их состояние можно сохранить в файл, либо загрузить из файла. У разных программ будет разный набор этих оконных компонентов, куда будут загружаться данные. Соответственно разная будет реализация функций Load и Save. Но они будут обращаться к данным класса формы. |
Автор: bsa 9.1.2013, 13:21 | ||||
Нитонисе, в стандарте С++ указатели на методы класса очень специфичные (я бы сказал - практически бесполезные субстанции). В Борландовской реализации есть более грамотные указатели (несут в себе не только указатель на сам код, но и на объект класса). Для их использования необходимо применять ключевое слово __closure. Поищи документацию во встроенной справке. Там все есть. Если же тебе хочется работать со стандартными указателями на метод, то делается это так:
Добавлено @ 13:25
А вот если программа одна, а "формы разные", то да, возможно ты мыслишь в правильном направлении. Но опять же. Не совсем. В Билдере есть уже для этого все что нужно. назначь на onClick вызов нужного метода нужного класса и все. |
Автор: Нитонисе 9.1.2013, 13:41 | ||||
bsa
Я заметил, что у меня от программы к программе копируется код по работе с файлом практически один в один, за исключением функций Load и Save. Поэтому и родилась идея все это привести к единому знаменателю. А какой OnClick предлагается обрабатывать - я не понял. Если имеется ввиду нажатие на кнопку открывающую/закрывающую файл - то конечно это сделать можно, но работа с файлом заключается не только в открытии и сохранении. Там еще контролируется состояние изменения, проверка корректности данных при открытии, при сохранении, вобщем есть ряд действий, которые одинаковы из программы в программу. |
Автор: mes 9.1.2013, 13:52 |
Нитонисе, посмотрите в доке (вот опять очередная отсылка ![]() |
Автор: bsa 9.1.2013, 13:54 |
исправил Сделай абстрактный класс, у которого функции load и save чисто виртуальные. А в каждой своей программе делай наследника, который переопределяет эти функции. Для этого наследование и существует. |
Автор: Нитонисе 9.1.2013, 18:26 | ||
Хм. Может это и хорошая идея в данном случае. |
Автор: bsa 9.1.2013, 19:56 |
Нитонисе, использование указателей на методы - это обычно всегда плохая идея. Чаще всего, они используются для реализации каких-нибудь "улучшайзеров" языка. Например, boost::bind (или std::bind), boost::function (std::function) и пр. В обычной жизни в них потребность крайне низка. И если вдруг тебе пришла в голову идея их использовать, подумай еще разик, может лучше подойдет наследование или шаблоны? |
Автор: mes 9.1.2013, 20:45 |
особенно, когда есть улучшайзеры )) вон и борланда они есть.. только кому лень в доку глянуть )) ..так и придется всю жизнь наследоваться... и проклинать наследование и ооп, как только встретится задача с "перехлестыванием интерфейсов" )) а раз пошли держать путь на модульность встретится и довольно скоро )) Добавлено через 1 минуту и 10 секунд ![]() |