Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
 
Inversus
0 / 0 / 0
Регистрация: 28.08.2016
Сообщений: 12
#1

Передача указателя на функцию-член - C++

29.08.2016, 00:05. Просмотров 1129. Ответов 41
Метки нет (Все метки)

Всем привет !

Необходимо передать функцию-член в качестве параметра другой функции-члену. Следующий код

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Menu {
    public:
    void spin();   
};
void Menu::spin() {
  ;
}
class Encoder {
  public:
    void setSpinFunc(void(Menu::*i)());
};
void Encoder::setSpinFunc(void(Menu::*i)()) {
  ;
}
int main()
{
    Menu m();
    Encoder e();
    e.setSpinFunc(m.spin);
}
вызывает ошибку: request for member 'setSpinFunc' in 'e', which is of non-class type 'Encoder()'

Уже долго туплю над этим, похоже сам не въеду, разъясните что не так.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
hoggy
6157 / 2523 / 443
Регистрация: 15.11.2014
Сообщений: 5,568
Завершенные тесты: 1
29.08.2016, 03:04     Передача указателя на функцию-член #2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Menu {
    public:
    void spin();   
};
void Menu::spin() {
  ;
}
class Encoder {
  public:
    void setSpinFunc(void(Menu::*)());
};
void Encoder::setSpinFunc(void(Menu::*i)()) {
  ;
}
int main()
{
    Menu m;
    Encoder e;
    e.setSpinFunc(&Menu::spin);
}
Добавлено через 3 минуты
это объявления прототипов функций.
Цитата Сообщение от Inversus Посмотреть сообщение
Menu m();
Encoder e();
вот здесь:
Цитата Сообщение от Inversus Посмотреть сообщение
request for member 'setSpinFunc' in 'e', which is of non-class type 'Encoder()'
компилятор как бы в недоумении.

у прототипов функций нельзя вызывать функции-члены.
это же не объекты классов.
Fulcrum_013
648 / 716 / 72
Регистрация: 14.12.2014
Сообщений: 5,608
Завершенные тесты: 3
29.08.2016, 06:02     Передача указателя на функцию-член #3
Цитата Сообщение от Inversus Посмотреть сообщение
Необходимо передать функцию-член в качестве параметра другой функции-члену.
Так определись сразу - функцию член класса или функцию-член объекта. Это две огромные разницы.
Inversus
0 / 0 / 0
Регистрация: 28.08.2016
Сообщений: 12
29.08.2016, 10:02  [ТС]     Передача указателя на функцию-член #4
Становится все интереснее)

это объявления прототипов функций.
Действительно, читается двояко. Хотя Я привык что прототипы пишутся перед main() - странно что вылазит именно такая ошибка. На самом деле у этих классов есть конструкторы с параметрами, здесь Я их просто убрал для упрощения.

В общем код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Menu {
    public:
    void spin();   
};
void Menu::spin() {
  ;
}
class Encoder {
  public:
    void setSpinFunc(void(Menu::*)());
};
void Encoder::setSpinFunc(void(Menu::*i)()) {
  ;
}
int main()
{
    Menu m;
    Encoder e;
    e.setSpinFunc(&Menu::spin);
}
действительно прокатывает, но как уточнил Fulcrum_013 - полагаю что мне нужно передавать именно функцию-член объекта.

Вот это (добавил конструкторы)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Menu {
    public:
    Menu::Menu(char* str)
    void spin();   
};
 
Menu::Menu(char* str) {
   ;
}
 
void Menu::spin() {
   ;
}
 
 
class Encoder {
  void (Menu::*spin)();
 
  public:
    Encoder(char a, char b, int p);
    void setSpinFunc(void(Menu::*i)());
};
 
Encoder::Encoder(char a, char b, int p) {
    ;
}
 
void Encoder::setSpinFunc(void(Menu::*i)()) {
  spin = i;
}
 
 
int main()
{
    Menu m("a1|a2|a3");
 
    Encoder e(1,2,3);
    e.setSpinFunc(m.spin);
}
-прокатывает в одном компиляторе и не прокатывает в другом -
no matching function for call to 'Encoder<Menu>::setSpinFunc(<unresolved overloaded function type>)'

Т.е. идея следующая - создается экземпляр Menu и экземпляр Encoder, в Encoder запоминается указатель на spin, и затем из некоторой функции-члена Encoder необходимо периодически вызывать spin. А в каких случаях может понадобиться передавать функцию-член класса ? Или можно и через класс и через объект ? Fulcrum_013, не затруднит дать развернутый ответ с примерами и с вызовом spin из Encoder ?
hoggy
6157 / 2523 / 443
Регистрация: 15.11.2014
Сообщений: 5,568
Завершенные тесты: 1
29.08.2016, 11:44     Передача указателя на функцию-член #5
Цитата Сообщение от Inversus Посмотреть сообщение
-прокатывает в одном компиляторе и не прокатывает в другом -
остановок "здеся" и "тута" не существует.

Цитата Сообщение от Inversus Посмотреть сообщение
действительно прокатывает, но как уточнил Fulcrum_013 - полагаю что мне нужно передавать именно функцию-член объекта.
он несет бред.

понятия "функция-член объекта" на плюсах не существует.

Цитата Сообщение от Inversus Посмотреть сообщение
А в каких случаях может понадобиться передавать функцию-член класса ?
http://rextester.com/FWEAP62520


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
 
struct Menu 
{
    void spin(){ std::cout << "Menu::spin\n"; }
};
 
struct Encoder 
{
  void (Menu::*spin)();
  Menu* menu;
 
    void setSpinFunc(void(Menu::*i)(), Menu& m)
    {
        menu = &m;
        spin = i;
    }
    
    void execute()
    {
        (menu->*spin)();
    }
};
 
 
 
int main()
{
    Menu m;
    Encoder e;
    e.setSpinFunc(&Menu::spin, m);
    e.execute();
}
Fulcrum_013
648 / 716 / 72
Регистрация: 14.12.2014
Сообщений: 5,608
Завершенные тесты: 3
29.08.2016, 19:51     Передача указателя на функцию-член #6
Цитата Сообщение от hoggy Посмотреть сообщение
понятия "функция-член объекта" на плюсах не существует
Поэтому и приходится наворачивать костыли для реализации делегата. Хотя разница лишь в добавлении к указателю на метод указателя на объект

Добавлено через 3 минуты
Цитата Сообщение от hoggy Посмотреть сообщение
он несет бред.
То вы бред несете. Если коммитет проглядел стандартизацию назревших 20 лет вещей это не значит что их не существует или в них не существует необходимости.

Добавлено через 14 минут
Цитата Сообщение от Inversus Посмотреть сообщение
полагаю что мне нужно передавать именно функцию-член объекта.
если нужно передовать указатель на член объекта то обычно делают так чтобы во всех компиляторах работало:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
typedef RetType (*HandlerProc)(Args);
class B:public BaseClass{
      public: 
             RetType Handler(Args){std::cout << "Delegate called"};
}
class A{
private:
      std::function<HandlerProc> Handler;
public:
       void SetHandler(std::function<HandlerProc> NewHandler){
                          Handler=NewHandler;
       };
       void Process(){
              //там где надо вызвать хандлер   
              if (Handler!=nullptr) Handler(Args);
              
       }
}
void main(){
       A a;
       B b;
       // инициализация делегата
      a.SetHandler([b](Args)->RetType{return b.Handler(Args;)});
      a.Process(); 
}
в общем с таким костылем через std::function и лямбду получается очень многословная и неудобная инициализация делегата.

Добавлено через 14 минут
Такая конструкция нужна когда A ничего не знает о B и/или может иметь несколько хандлеров в каждом из которых пользуются разные экземпляры B
Avazart
7063 / 5240 / 262
Регистрация: 10.12.2010
Сообщений: 23,051
Записей в блоге: 17
29.08.2016, 20:49     Передача указателя на функцию-член #7
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
То вы бред несете. Если коммитет проглядел стандартизацию назревших 20 лет вещей это не значит что их не существует или в них не существует необходимости.
Кому не нужно использует давно Qt или boost::signals2 и не закатывает истерик.
Fulcrum_013
648 / 716 / 72
Регистрация: 14.12.2014
Сообщений: 5,608
Завершенные тесты: 3
29.08.2016, 21:03     Передача указателя на функцию-член #8
Цитата Сообщение от Avazart Посмотреть сообщение
Кому не нужно использует давно Qt или boost::signals2 и не закатывает истерик.
Потому как в Qt имеется механизм делегатов которого нет в стандарте? Так такие механизмы есть в многих местах кроме стандарта, а соответственно и реализовываются несовместимо друг с другом. Не пора бы их стандартизировать?
Inversus
0 / 0 / 0
Регистрация: 28.08.2016
Сообщений: 12
29.08.2016, 21:34  [ТС]     Передача указателя на функцию-член #9
Японамать, мой чайник закипел

hoggy, спасибо, теперь буду знать что в стуктуры можно пихать функции

Т.е. что-бы вызвать функцию-член берем указатель на класс и добавляем смещение на функцию-член класса. У меня после JavaScript вообще теперь каша в голове

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
если нужно передавать указатель на член объекта то обычно делают так чтобы во всех компиляторах работало:
Спасибо, буду втыкать )

Цитата Сообщение от Avazart Посмотреть сообщение
использует давно Qt
Сам в нем пишу что можно, жаль только под Arduino не адаптирован.
Avazart
7063 / 5240 / 262
Регистрация: 10.12.2010
Сообщений: 23,051
Записей в блоге: 17
29.08.2016, 21:41     Передача указателя на функцию-член #10
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Не пора бы их стандартизировать?
Понту говорить о том чего нет... и на вряд ли будет...
Fulcrum_013
648 / 716 / 72
Регистрация: 14.12.2014
Сообщений: 5,608
Завершенные тесты: 3
29.08.2016, 21:43     Передача указателя на функцию-член #11
Цитата Сообщение от Inversus Посмотреть сообщение
теперь буду знать что в стуктуры можно пихать функции
Их еще и наследовать можно. По большому счету теперь структуры отличаются от классов только тем что у структур по умолчанию public видимость и public наследование.

Добавлено через 1 минуту
Цитата Сообщение от Avazart Посмотреть сообщение
Понту говорить о том чего нет... и на вряд ли будет...
Ну да... эпоха визуальной разработки а необходимые для этого средства коммитет стандартизировать как понимаю не собирается.. КОММИТЕТ АКБАР!!!
Avazart
7063 / 5240 / 262
Регистрация: 10.12.2010
Сообщений: 23,051
Записей в блоге: 17
29.08.2016, 21:45     Передача указателя на функцию-член #12
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
эпоха визуальной разработки
Давно прошла... В месте с популярностью Delphi где-то.
Fulcrum_013
648 / 716 / 72
Регистрация: 14.12.2014
Сообщений: 5,608
Завершенные тесты: 3
29.08.2016, 21:47     Передача указателя на функцию-член #13
Цитата Сообщение от Avazart Посмотреть сообщение
Давно прошла...
угу. Qt тоже средство визуальной разработки. И MSVC вроде бы как таковое даже по названию позиционируется. И чем дальше тем больше задачи становятся обычно задачами разработки средств визуальной разработки для нужд конечного пользователя. А эпоха дельфы вернее Билдера по большому счету еще не наступила.
Вообще концепция КОП заключается в том что непосредственно бизнес-логику должны визуально собирать менеджеры из настриваемых визуальных блоков которые изготавливают программисты.
Кстати такой подход не только в баксосчитании пользуется. К примеру Simantec Step 7 тоже на этой идеологии держится как и многие SCADA-системы.
Avazart
7063 / 5240 / 262
Регистрация: 10.12.2010
Сообщений: 23,051
Записей в блоге: 17
29.08.2016, 21:56     Передача указателя на функцию-член #14
MSVC продвигает давно C# у которого "включено".

Добавлено через 4 минуты
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
И чем дальше тем больше задачи становятся обычно задачами разработки средств визуальной разработки для нужд конечного пользователя.
Очнись, некоторые С++ разработчики даже GUI не касаются, пишут себе сервера и консольки....
А учитывая что единого стандартизированного GUI (а значит кроссплатформенного) нет в С++ то и этот вопрос не настолько актуален.

Добавлено через 3 минуты
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
А эпоха дельфы вернее Билдера по большому счету еще не наступила.
Что б тебя динозавры съели )) В какая это эпоха... Они фиг знает сколько готовый компилятор пилили с начало под одну платформу(x64) потом под другую... потом вылезли динамические зависимости.... бока... бока... и их они по два три года не исправляют... Все спехом все через ...
Fulcrum_013
648 / 716 / 72
Регистрация: 14.12.2014
Сообщений: 5,608
Завершенные тесты: 3
29.08.2016, 23:00     Передача указателя на функцию-член #15
Цитата Сообщение от Avazart Посмотреть сообщение
Очнись, некоторые С++ разработчики даже GUI не касаются, пишут себе сервера и консольки....
Это не значит что при обработке данных сервом и консолькой не нужны делегаты или не возможно преимущественно визуальное проектирование ливера этих сервов.

Добавлено через 8 минут
Цитата Сообщение от Avazart Посмотреть сообщение
Очнись, некоторые С++ разработчики даже GUI не касаются, пишут себе сервера и консольки....
И даже внутренности контроллеров с использованием визуальной разработки.
Цитата Сообщение от Avazart Посмотреть сообщение
А учитывая что единого стандартизированного GUI (а значит кроссплатформенного) нет в С++ то и этот вопрос не настолько актуален.
Единого нет. Но для визуальной разработки каким бы оно ни было (причем не только GUI) нужны единые языковые инструменты. А именно свойства делегаты и RTTI в объеме который называют reflection. При этом reflection и свойства нужны еще и для полиморфной сериализации/десериализации объектов, а где пользовать делегаты мест тоже найдется куча и не касаемо GUI. Все таки на дворе уже 40 лет как эпоха событийного управления. Причем реализация нативной поддержки всего этого в компиляторах будет гораздо менее сложной чем те дела которые непонятно зачем комитет пихает в стандарт и не будут приводить к ограничению в механизмах используемых в программах (к примеру в отличии от автоматического рефкаунтинга который непонятно с какой целью сунули в 17-ый стандарт)

Добавлено через 16 минут
Цитата Сообщение от Avazart Посмотреть сообщение
Они фиг знает сколько готовый компилятор пилили с начало под одну платформу(x64) потом под другую... потом вылезли динамические зависимости....
Хорошие вещи быстро не делаются. И без боков не делаются. Боков не бывает только у тех кто вообще ничего не делает. К примеру "Союз" тоже далеко не с первого запуска полетел. Так же как и Falcon-9. А к примеру "Бураны" тоже не летают потому что их эпоха еще не наступила (хотя эпоха внешне очень похожих шаттлов уже закончилась). При этом к примеру бортовой софт "Бурана" и "Энергии" на 100% на событийном управлении и на 100% визуальной разработки (правда не ООП)

Добавлено через 30 минут
Цитата Сообщение от Avazart Посмотреть сообщение
некоторые С++ разработчики даже GUI не касаются
К примеру TDataModule в С++ Builder тоже GUI не касается. Но тем не менее компоненты которые в нем размещаются тоже связываются и настраиваются преимущественно визуально.
Avazart
7063 / 5240 / 262
Регистрация: 10.12.2010
Сообщений: 23,051
Записей в блоге: 17
29.08.2016, 23:03     Передача указателя на функцию-член #16
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Хорошие вещи быстро не делаются. И без боков не делаются.
Ну явно не пятилетками, это все же IT - либо вовремя либо никогда.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Это не значит что при обработке данных сервом и консолькой не нужны делегаты или не возможно преимущественно визуальное проектирование ливера этих сервов.
Например, зачем это нужно в коде сервера или консольке?

Добавлено через 3 минуты
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
К примеру TDataModule в С++ Builder тоже GUI не касается. Но тем не менее компоненты которые в нем размещаются тоже связываются и настраиваются преимущественно визуально.
Нарушая при этом инкапсуляцию. Это как раз беда билдера.
Для работы с БД это еще более или менее...
Но для работы к примеру в потоке все равно придется создавать и настраивать компоненты в коде.
Fulcrum_013
648 / 716 / 72
Регистрация: 14.12.2014
Сообщений: 5,608
Завершенные тесты: 3
29.08.2016, 23:06     Передача указателя на функцию-член #17
Цитата Сообщение от Avazart Посмотреть сообщение
Например, зачем это нужно в коде сервера?
Пример - на сокет пришла информация. Необходимо оповестить обрабатывающий контекст. Сокет отправил данные. Тоже надо контекст оповестить. Коннект опять же нужно контекст оповестить. Дисконнет то же самое. Не кажется ли что все это внутри одного процесса удобнее делать через делегата чем через мессаджи? А даже если и через мессаджи то подписку на получение события из системы диспетчеризации сообщений тоже удобно через делегаты делать. Ну и так вобщем на каждом шагу. Чем больше взаимосвязей между объектами информационой модели тем от большего головняка при проектировании иерархии избавляют делегаты.
Avazart
7063 / 5240 / 262
Регистрация: 10.12.2010
Сообщений: 23,051
Записей в блоге: 17
29.08.2016, 23:09     Передача указателя на функцию-член #18
А вы гляньте в boost/asio. Я не вижу такую необходимости.
Fulcrum_013
648 / 716 / 72
Регистрация: 14.12.2014
Сообщений: 5,608
Завершенные тесты: 3
29.08.2016, 23:18     Передача указателя на функцию-член #19
Цитата Сообщение от Avazart Посмотреть сообщение
Нарушая при этом инкапсуляцию.
Что конкретно подразумевается под нарушением инкапсуляции? Да кстати очень часто нарушение инкапсуляции дает абсолютную инкапсуляцию на более высоком уровне. (Сокрытие и обеспечение невмешательства извне в механизм взаимодействия объектов двух или нескольких классов)
Как на меня нарушение инкапсуляции это к примеру публичные а не протектед геттеры и сеттеры.

Добавлено через 4 минуты
Цитата Сообщение от Avazart Посмотреть сообщение
Я не вижу такую необходимости
Если контексты-обработчики объекты то необходимость такая есть как бы механизм ее реализации не был организован. К примеру можно костылить через std и лямбды, можно через статик методы - посредники и передачу багажом контекста, а можно через нативную поддержку делегата который в принципе делает то же самое только с гораздо более удобным синтаксисом и гораздо меньшим количеством кода.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.08.2016, 23:20     Передача указателя на функцию-член
Еще ссылки по теме:

Передача ссылки и указателя в функцию C++
Передача указателя в функцию по ссылке C++
C++ Передача указателя в функцию
Передача указателя на функцию C++
C++ Передача указателя на шаблонную функцию в другую функцию

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Avazart
7063 / 5240 / 262
Регистрация: 10.12.2010
Сообщений: 23,051
Записей в блоге: 17
29.08.2016, 23:20     Передача указателя на функцию-член #20
К примеру что мешает сделать так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void AbstractMenu
{
    public:
        virtual void spin()=0;   
};
 
 
class Menu: public AbstractMenu
{
    public:
    virtual void spin();   
};
 
 
void Menu::spin() 
{
};
 
 
class Encoder {
  public:
    void setSpinFunc(AbstractMenu* menu);
};
void Encoder::setSpinFunc(AbstractMenu* menu) 
{
     menu->spin();
}
int main()
{
    Menu m();
    Encoder e();
    e.setSpinFunc(&m);
}
Добавлено через 1 минуту
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Что конкретно подразумевается под нарушением инкапсуляции?
Компоненты видны "снаружи" модуля, так как находятся в секции __published
Yandex
Объявления
29.08.2016, 23:20     Передача указателя на функцию-член
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru