Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.59/29: Рейтинг темы: голосов - 29, средняя оценка - 4.59
7 / 7 / 0
Регистрация: 16.11.2012
Сообщений: 84
1

Указатель на функцию-член класса

28.06.2015, 21:11. Показов 5452. Ответов 2
Метки нет (Все метки)

Нужно передать указатель на функцию класса A изнутри самого класса А в функцию, в качестве аргумента классу B.

Осторожно, говнокод
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
40
41
42
43
44
45
46
47
48
49
#include <Windows.h>
#include <vector>
 
class ThreadManager
{
    
 
public:
    typedef void* fPointer;
 
    ThreadManager(){
        fx.resize(1);
    }
 
    ~ThreadManager(){};
 
    std::vector<fPointer> GetFunctionsList(){
        return fx;
    }
 
    void StartFunction(int FID){
        currentFuncNumber = FID;
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)fCaller, this, 0, NULL);
    }
 
    int AddFuction(fPointer functionAddress){ //А конкретнее - сюда
        currentFuncNumber = fx.size() - 1;
        fx[currentFuncNumber] = functionAddress;
        fx.resize(fx.size() + 1);
        return currentFuncNumber;
    }
 
private:
    std::vector<fPointer> fx;
    int currentFuncNumber;
 
    void StartFunction(){
        void (*f)();
        f = static_cast<void(*)()>(fx[currentFuncNumber]);
        f();
    }
 
    static DWORD fCaller(LPVOID* param)
    {
        ThreadManager* myClass = (ThreadManager*)param;
        myClass->StartFunction();
        return 0;
    }
};

ЗЫ: Заранее благодарен за ответ и буду признателен за предложения альтернатив моему говнокоду ;)
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.06.2015, 21:11
Ответы с готовыми решениями:

Указатель на функцию - член класса.
делаю так: class c1 { void foo(); } class c2 { void (*fp)();

Не могу создать указатель на перегруженную функцию-член класса
Есть функция монстр из vulkan api. Она является членом класса. Просто написать её название не...

Указатель на функцию-член одного класса в другом классе - C++
Добрый вечер! Может кто-то может помочь с проблемой. class Cook { public: void ...

std::bind и указатель на статическую функцию член класса
Биндинг простых функций класса-это понятно, а вот как быть, если функция статическая?

2
шКодер самоучка
2145 / 1856 / 907
Регистрация: 09.10.2013
Сообщений: 4,055
Записей в блоге: 7
28.06.2015, 21:23 2
там довольно страшный синтаксис
C++
1
2
3
4
5
6
7
typedef return_type (A::*a_member)(param_type);
//...
a_member func_ptr = &A::some_func;
A a;
a.*func_ptr(param);
A* a_ptr = new A;
a->*func_ptr(param);
для вызова функции члена нужно 2 указателя - собственно указатель на функцию + указатель на объект, к которому применяется вызов данной функции(тот, что будет использоваться внтри в качестве this)

Добавлено через 4 минуты
альтернативой может быть std::function + std::bind из <functional>
1
Эксперт С++
8426 / 4099 / 894
Регистрация: 15.11.2014
Сообщений: 9,211
28.06.2015, 22:02 3
Цитата Сообщение от Misterkat Посмотреть сообщение
Нужно передать указатель на функцию класса A изнутри самого класса А в функцию, в качестве аргумента классу B.
в вашем случае это не прокатит.
потому что помимо указателя на функцию-член,
требуется так же объект,
для которого нужно запустить функцию-член

пример:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <Windows.h>
#include <functional>
#include <iostream>
#include <vector>
 
 
 
class ThreadManager
{
public:
    //typedef void* fPointer;
    typedef std::function<void()>
        fPointer;
 
    ThreadManager() {
        fx.resize(1); 
    }
 
    ~ThreadManager(){};
 
    std::vector<fPointer> GetFunctionsList(){ 
        return fx; 
    }
 
    void StartFunction(int FID){
        currentFuncNumber = FID;
        CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fCaller,this,0,NULL);
    }
 
    int AddFuction(fPointer functionAddress){ //А конкретнее - сюда
        currentFuncNumber = fx.size() - 1;
        fx[currentFuncNumber] = functionAddress;
        fx.resize(fx.size() + 1);
        return currentFuncNumber;
    }
 
private:
    std::vector<fPointer> fx;
    int currentFuncNumber;
 
    void StartFunction(){
 
        fx[currentFuncNumber]();
        /*
        void(*f)();
        f = static_cast<void(*)()>(fx[currentFuncNumber]);
        f();
        */
    }
 
    static DWORD fCaller(LPVOID* param)
    {
        ThreadManager* myClass = (ThreadManager*)param;
        myClass->StartFunction();
        return 0;
    }
};
 
 
void threadFunc(){
    std::cout<<"thread was launched\n";
}
 
struct example
{
    void threadFunc(){
        std::cout<<"example::thread was launched\n";
    }
};
 
int main()
{
    ThreadManager manager;
 
    // запускаем в отдельном треде свободную функцию 
    const auto id1 = manager.AddFuction(&threadFunc);
 
    example obj;
 
    // запускаем в отдельном треде метод класса для объекта obj
    // при этом сам объект копируется по значению
    const auto id2 = manager.AddFuction(std::bind(&example::threadFunc,obj));
 
    // запускаем в отдельном треде метод класса для объекта obj
    // при этом сам объект не копируется, а используется ссылка на внешний
    const auto id3 = manager.AddFuction( std::bind(&example::threadFunc, std::ref(obj))  );
 
    manager.StartFunction(id1);
    manager.StartFunction(id2);
    manager.StartFunction(id3);
 
    system("pause");
}
Добавлено через 18 минут
если вам смущают уродливые бинды:
C++
1
2
const auto id3 
    = manager.AddFuction( std::bind(&example::threadFunc, std::ref(obj))  );
то можно увеличить удобство использования менеджера,
упрятав бинды в коде самого менеджера:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <Windows.h>
#include <functional>
#include <iostream>
#include <vector>
#include <thread>
 
 
 
class ThreadManager
{
public:
    //typedef void* fPointer;
    typedef std::function<void()>
        fPointer;
 
    ThreadManager() { 
        fx.resize(1); 
    }
 
    ~ThreadManager(){};
 
    std::vector<fPointer> GetFunctionsList() {
        return fx; 
    }
 
    void StartFunction(int FID){
        currentFuncNumber = FID;
        CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fCaller,this,0,NULL);
    }
 
    template<typename F, class T>
    int AddFuction(F functionAddress, T& obj){ 
        const auto method = std::bind(functionAddress, std::ref(obj));
        return AddFuction(method);
    }
    template<typename F, class T>
    int AddFuction(F functionAddress, T&& obj){ 
        const auto method = std::bind(functionAddress,obj);
        return AddFuction(method);
    }
 
    int AddFuction(fPointer functionAddress){ //А конкретнее - сюда
        currentFuncNumber = fx.size() - 1;
        fx[currentFuncNumber] = functionAddress;
        fx.resize(fx.size() + 1);
        return currentFuncNumber;
    }
 
private:
    std::vector<fPointer> fx;
    int currentFuncNumber;
 
    void StartFunction(){
 
        fx[currentFuncNumber]();
        /*
        void(*f)();
        f = static_cast<void(*)()>(fx[currentFuncNumber]);
        f();
        */
    }
 
    static DWORD fCaller(LPVOID* param)
    {
        ThreadManager* myClass = (ThreadManager*)param;
        myClass->StartFunction();
        return 0;
    }
};
 
 
void threadFunc(){
    std::cout<<"thread was launched\n";
}
 
struct example
{
    void threadFunc(){
        std::cout<<"example::thread was launched\n";
    }
};
 
int main()
{
    ThreadManager manager;
 
    // запускаем в отдельном треде свободную функцию 
    const auto id1 = manager.AddFuction(&threadFunc);
 
    example obj;
 
    // запускаем в отдельном треде метод класса для объекта obj
    // при этом сам объект копируется по значению
    const auto id2 = manager.AddFuction(std::bind(&example::threadFunc,obj));
 
    // запускаем в отдельном треде метод класса для объекта obj
    // при этом сам объект не копируется, а используется ссылка на внешний
    const auto id3 = manager.AddFuction( std::bind(&example::threadFunc, std::ref(obj))  );
 
 
 
    // obj по ссылке
    const auto id4 = manager.AddFuction( &example::threadFunc, obj );
 
    // obj - временный объект, по значению
    const auto id5 = manager.AddFuction( &example::threadFunc, example() );
 
 
    const auto delay = std::chrono::microseconds(1000000);
 
    manager.StartFunction(id1);
    std::this_thread::sleep_for(delay);
    manager.StartFunction(id2);
    std::this_thread::sleep_for(delay);
    manager.StartFunction(id3);
    std::this_thread::sleep_for(delay);
    manager.StartFunction(id4);
    std::this_thread::sleep_for(delay);
    manager.StartFunction(id5);
    std::this_thread::sleep_for(delay);
}
ну и напоследок:
обратите внимание на заголовочный файл:
C++
1
 #include <thread>
в своем примере, я использовал его для организации задержки:
C++
1
std::this_thread::sleep_for(delay);
но на самом деле это - стандартные потоки
умеют все тоже самое, что и WINAPI`шные.
но гораздо мощнее и удобнее.

с их помощью код получается портируемым под другие платформы
(а винапи только под виндовс)

и код мог бы выглядеть, например, так:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <functional>
#include <iostream>
#include <vector>
#include <thread>
 
class ThreadManager
{
public:
    typedef std::function<void()>
        fPointer;
 
    ThreadManager() { 
        fx.resize(1); 
    }
 
    ~ThreadManager(){};
 
    std::vector<fPointer> GetFunctionsList() {
        return fx; 
    }
 
    void StartFunction(int FID){
        std::thread(fx[FID]).detach();
    }
 
    template<typename F, class T>
    int AddFuction(F functionAddress, T& obj){ 
        const auto method = std::bind(functionAddress, std::ref(obj));
        return AddFuction(method);
    }
    template<typename F, class T>
    int AddFuction(F functionAddress, T&& obj){ 
        const auto method = std::bind(functionAddress,obj);
        return AddFuction(method);
    }
 
    int AddFuction(fPointer functionAddress){ 
        fx.emplace_back(functionAddress);
        return fx.size()-1;
    }
 
private:
    std::vector<fPointer> fx;
};
 
 
void threadFunc(){
    std::cout<<"thread was launched\n";
}
 
struct example
{
    void threadFunc(){
        std::cout<<"example::thread was launched\n";
    }
};
 
int main()
{
    ThreadManager manager;
 
    // запускаем в отдельном треде свободную функцию 
    const auto id1 = manager.AddFuction(&threadFunc);
 
    example obj;
 
    // запускаем в отдельном треде метод класса для объекта obj
    // при этом сам объект копируется по значению
    const auto id2 = manager.AddFuction(std::bind(&example::threadFunc,obj));
 
    // запускаем в отдельном треде метод класса для объекта obj
    // при этом сам объект не копируется, а используется ссылка на внешний
    const auto id3 = manager.AddFuction( std::bind(&example::threadFunc, std::ref(obj))  );
 
 
 
    // obj по ссылке
    const auto id4 = manager.AddFuction( &example::threadFunc, obj );
 
    // obj - временный объект, по значению
    const auto id5 = manager.AddFuction( &example::threadFunc, example() );
 
 
    const auto delay = std::chrono::microseconds(1000000);
 
    manager.StartFunction(id1);
    std::this_thread::sleep_for(delay);
    manager.StartFunction(id2);
    std::this_thread::sleep_for(delay);
    manager.StartFunction(id3);
    std::this_thread::sleep_for(delay);
    manager.StartFunction(id4);
    std::this_thread::sleep_for(delay);
    manager.StartFunction(id5);
    std::this_thread::sleep_for(delay);
}
Добавлено через 7 минут
плюс, используя стандартные треды,
можно запускать любые функции,
или функции члены с самым разным набором входных аргументов.

при этом, проверка на ошибки будет времени компиляции:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <functional>
#include <iostream>
#include <vector>
#include <string>
#include <thread>
 
class ThreadManager
{
public:
    typedef std::function<void()>
        fPointer;
 
    ThreadManager() { 
        fx.resize(1); 
    }
 
    ~ThreadManager(){};
 
    std::vector<fPointer> GetFunctionsList() {
        return fx; 
    }
 
    void StartFunction(int FID){
        std::thread(fx[FID]).detach();
    }
 
    template<typename F, class T, typename ... Args>
    int AddFuction(F functionAddress, T& obj, Args&&... args){ 
        const auto method = std::bind(functionAddress, std::ref(obj), std::forward<Args>(args)...);
        return AddFuction(method);
    }
    template<typename F, class T, typename ... Args>
    int AddFuction(F functionAddress, T&& obj, Args&&... args){ 
        const auto method = std::bind(functionAddress,obj, std::forward<Args>(args)...);
        return AddFuction(method);
    }
 
    int AddFuction(fPointer functionAddress){ 
        fx.emplace_back(functionAddress);
        return fx.size()-1;
    }
 
private:
    std::vector<fPointer> fx;
};
 
 
void threadFunc(){
    std::cout<<"thread was launched\n";
}
 
struct example
{
    void threadFunc(){
        std::cout<<"example::thread was launched\n";
    }
 
    void threadFuncWithParam(int v, const std::string& text){
        std::cout<<"example::threadFuncWithParam(" << v <<", " << text << ")\n";
    }
};
 
int main()
{
    ThreadManager manager;
 
    // запускаем в отдельном треде свободную функцию 
    const auto id1 = manager.AddFuction(&threadFunc);
 
    example obj;
 
    // запускаем в отдельном треде метод класса для объекта obj
    // при этом сам объект копируется по значению
    const auto id2 = manager.AddFuction(std::bind(&example::threadFunc,obj));
 
    // запускаем в отдельном треде метод класса для объекта obj
    // при этом сам объект не копируется, а используется ссылка на внешний
    const auto id3 = manager.AddFuction( std::bind(&example::threadFunc, std::ref(obj))  );
 
 
 
    // obj по ссылке
    const auto id4 = manager.AddFuction( &example::threadFunc, obj );
 
    // obj - временный объект, по значению
    const auto id5 = manager.AddFuction( &example::threadFunc, example() );
 
    // запуск функции с произвольными параметрами
    const auto id6 = manager.AddFuction(&example::threadFuncWithParam,example(), 10, "hello");
 
 
    const auto delay = std::chrono::microseconds(1000000);
 
    manager.StartFunction(id1);
        std::this_thread::sleep_for(delay);
 
    manager.StartFunction(id2);
        std::this_thread::sleep_for(delay);
 
    manager.StartFunction(id3);
        std::this_thread::sleep_for(delay);
 
    manager.StartFunction(id4);
        std::this_thread::sleep_for(delay);
 
    manager.StartFunction(id5);
        std::this_thread::sleep_for(delay);
 
    manager.StartFunction(id6);
        std::this_thread::sleep_for(delay);
}
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.06.2015, 22:02

Как создать указатель на функцию-член класса и вызвать его?
Подскажите как правильно сделать, а в дальнейшем вызвать указатель на функцию член класса:...

Указатель на член структуры/класса
Всем привет! Помогите разобраться. Пусть есть такой код: template &lt;typename Type&gt; class...

Указатель на ф-цию член класса
Чёрная магия или я бот? g++ sub.cpp:21: error: expected unqualified-id before ‘*’ token...

Что такое указатель на член класса?
Что такое указатель на член класса?


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

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Опции темы

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