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

C++

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

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

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

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

Шаблон RAII замены указателя на функцию - C++
шаблон raii замены указателя на фукнцию допустим имеется набор указателей на функции разных типов и существует потребность временно,...

Вызов через указатель на функцию-член - C++
Всем экспертам привет :) Разбавим раздел, так сказать. Задался тут таким вопросом: Есть класс, в котором объявлено поле типа...

Ошибка Access violation при передаче указателя в функцию - C++
выделяю память для нужд програмных и соханяю его. char *resadres =(char*) VirtualAlloc (0, 50000, MEM_COMMIT | MEM_RESERVE,...

Передача ссылки в функцию в DLL - C++
Здравствуйте. По этому мануалу сделал DLL https://msdn.microsoft.com/ru-ru/library/ms235636.aspx Возникла проблема с передачей...

Передача и возврат указателя из массива - C++ Builder
Доброго времени суток. проблема с указателями как я догадываюсь. функция im исправно работает исправно но при объединение с...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
hoggy
6535 / 2715 / 469
Регистрация: 15.11.2014
Сообщений: 5,996
Завершенные тесты: 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
664 / 732 / 72
Регистрация: 14.12.2014
Сообщений: 5,701
Завершенные тесты: 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
6535 / 2715 / 469
Регистрация: 15.11.2014
Сообщений: 5,996
Завершенные тесты: 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
664 / 732 / 72
Регистрация: 14.12.2014
Сообщений: 5,701
Завершенные тесты: 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
Эксперт С++
7151 / 5328 / 277
Регистрация: 10.12.2010
Сообщений: 23,578
Записей в блоге: 17
29.08.2016, 20:49 #7
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
То вы бред несете. Если коммитет проглядел стандартизацию назревших 20 лет вещей это не значит что их не существует или в них не существует необходимости.
Кому не нужно использует давно Qt или boost::signals2 и не закатывает истерик.
Fulcrum_013
664 / 732 / 72
Регистрация: 14.12.2014
Сообщений: 5,701
Завершенные тесты: 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
Эксперт С++
7151 / 5328 / 277
Регистрация: 10.12.2010
Сообщений: 23,578
Записей в блоге: 17
29.08.2016, 21:41 #10
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Не пора бы их стандартизировать?
Понту говорить о том чего нет... и на вряд ли будет...
Fulcrum_013
664 / 732 / 72
Регистрация: 14.12.2014
Сообщений: 5,701
Завершенные тесты: 3
29.08.2016, 21:43 #11
Цитата Сообщение от Inversus Посмотреть сообщение
теперь буду знать что в стуктуры можно пихать функции
Их еще и наследовать можно. По большому счету теперь структуры отличаются от классов только тем что у структур по умолчанию public видимость и public наследование.

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

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

Добавлено через 3 минуты
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
А эпоха дельфы вернее Билдера по большому счету еще не наступила.
Что б тебя динозавры съели )) В какая это эпоха... Они фиг знает сколько готовый компилятор пилили с начало под одну платформу(x64) потом под другую... потом вылезли динамические зависимости.... бока... бока... и их они по два три года не исправляют... Все спехом все через ...
Fulcrum_013
664 / 732 / 72
Регистрация: 14.12.2014
Сообщений: 5,701
Завершенные тесты: 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 не касается. Но тем не менее компоненты которые в нем размещаются тоже связываются и настраиваются преимущественно визуально.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.08.2016, 23:00
Привет! Вот еще темы с ответами:

Передача указателя на объект класса через this - C++ Builder
Всем участникам форума горячий ПРИВЕТ! Вопрос такой. cl.h class cl { public: void cl(); int a; private: DWORD...

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

Передача указателя на шаблонную функцию в другую функцию - C++
Пишу тест для нескольких улучшений квиксорта с измерением времени. Функция benchmark принимает итераторы для диапазона элементов, указатель...

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


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
29.08.2016, 23:00
Ответ Создать тему
Опции темы

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