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

C++

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

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

29.08.2016, 00:05. Просмотров 1218. Ответов 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()'

Уже долго туплю над этим, похоже сам не въеду, разъясните что не так.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.08.2016, 00:05     Передача указателя на функцию-член
Посмотрите здесь:

Передача указателя на функцию-член класса - C++
Необходимо передать фунцию-член класса как аргумент в функцию другого класса. Код: Файл main.cpp #include "head.hpp" int...

Передача указателя в функцию - C++
Здравствуйте. Прошу помощи, сижу уже пару часов читаю мануалы, но так и не смог до конца понять, что мне делать. Есть вот такой код: ...

Передача указателя на функцию - C++
Есть класс в котором: typedef void(*setChar)(int x, int y, wchar_t c); void Paint(setChar SetChar) В другом классе...

Передача указателя в функцию - C++
Поиском не пользовался, возможно данный вопрос уже проскакивал. Проблема том, что VS2010 на отрез отказывается передавать указатель на...

Передача указателя на функцию - C++
Доброго дня Форумчане. Хотелось бы узнать как вызывать функцию получив на нее указатель? пример class C1 { public: void...

Передача указателя в функцию - C++
Здраствуйте. Если не охота читать гору текста то этот абзац + последущий за ним код можете пропустить. Задали на лабе сделать некий...

Передача в функцию указателя - C++
Почему плохо передавать в функцию указатель на строку или массив и возвращать указатель на строку или массив?

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
hoggy
6413 / 2631 / 457
Регистрация: 15.11.2014
Сообщений: 5,808
Завершенные тесты: 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
663 / 731 / 72
Регистрация: 14.12.2014
Сообщений: 5,699
Завершенные тесты: 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
6413 / 2631 / 457
Регистрация: 15.11.2014
Сообщений: 5,808
Завершенные тесты: 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
663 / 731 / 72
Регистрация: 14.12.2014
Сообщений: 5,699
Завершенные тесты: 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
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,387
Записей в блоге: 17
29.08.2016, 20:49     Передача указателя на функцию-член #7
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
То вы бред несете. Если коммитет проглядел стандартизацию назревших 20 лет вещей это не значит что их не существует или в них не существует необходимости.
Кому не нужно использует давно Qt или boost::signals2 и не закатывает истерик.
Fulcrum_013
663 / 731 / 72
Регистрация: 14.12.2014
Сообщений: 5,699
Завершенные тесты: 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
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,387
Записей в блоге: 17
29.08.2016, 21:41     Передача указателя на функцию-член #10
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Не пора бы их стандартизировать?
Понту говорить о том чего нет... и на вряд ли будет...
Fulcrum_013
663 / 731 / 72
Регистрация: 14.12.2014
Сообщений: 5,699
Завершенные тесты: 3
29.08.2016, 21:43     Передача указателя на функцию-член #11
Цитата Сообщение от Inversus Посмотреть сообщение
теперь буду знать что в стуктуры можно пихать функции
Их еще и наследовать можно. По большому счету теперь структуры отличаются от классов только тем что у структур по умолчанию public видимость и public наследование.

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

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

Добавлено через 3 минуты
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
А эпоха дельфы вернее Билдера по большому счету еще не наступила.
Что б тебя динозавры съели )) В какая это эпоха... Они фиг знает сколько готовый компилятор пилили с начало под одну платформу(x64) потом под другую... потом вылезли динамические зависимости.... бока... бока... и их они по два три года не исправляют... Все спехом все через ...
Fulcrum_013
663 / 731 / 72
Регистрация: 14.12.2014
Сообщений: 5,699
Завершенные тесты: 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
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,387
Записей в блоге: 17
29.08.2016, 23:03     Передача указателя на функцию-член #16
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Хорошие вещи быстро не делаются. И без боков не делаются.
Ну явно не пятилетками, это все же IT - либо вовремя либо никогда.

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

Добавлено через 3 минуты
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
К примеру TDataModule в С++ Builder тоже GUI не касается. Но тем не менее компоненты которые в нем размещаются тоже связываются и настраиваются преимущественно визуально.
Нарушая при этом инкапсуляцию. Это как раз беда билдера.
Для работы с БД это еще более или менее...
Но для работы к примеру в потоке все равно придется создавать и настраивать компоненты в коде.
Fulcrum_013
663 / 731 / 72
Регистрация: 14.12.2014
Сообщений: 5,699
Завершенные тесты: 3
29.08.2016, 23:06     Передача указателя на функцию-член #17
Цитата Сообщение от Avazart Посмотреть сообщение
Например, зачем это нужно в коде сервера?
Пример - на сокет пришла информация. Необходимо оповестить обрабатывающий контекст. Сокет отправил данные. Тоже надо контекст оповестить. Коннект опять же нужно контекст оповестить. Дисконнет то же самое. Не кажется ли что все это внутри одного процесса удобнее делать через делегата чем через мессаджи? А даже если и через мессаджи то подписку на получение события из системы диспетчеризации сообщений тоже удобно через делегаты делать. Ну и так вобщем на каждом шагу. Чем больше взаимосвязей между объектами информационой модели тем от большего головняка при проектировании иерархии избавляют делегаты.
Avazart
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,387
Записей в блоге: 17
29.08.2016, 23:09     Передача указателя на функцию-член #18
А вы гляньте в boost/asio. Я не вижу такую необходимости.
Fulcrum_013
663 / 731 / 72
Регистрация: 14.12.2014
Сообщений: 5,699
Завершенные тесты: 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++
Подскажите плиз. Есть некий класс и в нём метод: ... DWORD WINAPI func(LPVOID lParam) { ... return 1; } ...

Передача указателя в функцию по ссылке - C++
Почему невозможно передать указатель в функцию по ссылке? void function(int &amp; (*a)){ ... ... ... } void main(){ int x; ...

Передача типа указателя на функцию - C++
Всем привет. Недавно в теме начинающих возник вопрос, а можно ли передать тип (указатель на функцию) без использования typedef: ...

Передача указателя на CALLBACK функцию - C++ WinAPI
делаю класс приложения для более быстрого создания программ и просто инкапсуляции всего и вся)) и вот я сделал класс cApplication, один...

Передача в функцию указателя на указатель - C++
Добавление нового элемента в начало списка: void Add_Beg(List **u, Data &amp;x) // Почему в 1 аргументе функции указатель на указатель? { ...


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

Или воспользуйтесь поиском по форуму:
Avazart
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,387
Записей в блоге: 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