Сообщение от
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
| 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);
} |
|