Здравствуйте, Нартов Андрей Евгеньевич, Вы писали:
A>>уточните зачем это надо.
НАЕ>например, сделать нить (CreateThread()) из нестатической member function
<>
НАЕ>Но ведь должен быть какой-то способ сделать такое преобразование указателей?
Преобразование указателей — нет такого способа (в общем виде). И вот почему.
Указатель на функцию или статический метод — это указатель в сегменте кода. Его размер для intel/win32 равен 4.
Указатель на метод — это совершенно иное явление. Он содержит разнообразную дополнительную информацию — о виртуальном методе, о виртуальной базе — и достигает размера 20 байт.
Чтобы передать в нить связку (closure) объекта и метода, нужно воспользоваться шлюзом (thunk).
Пример
template<class V>
V* assert_non_null(V* v) { assert(v != NULL); return v; }
template<class T>
struct Thunk
{
typedef T Type;
typedef Thunk<T> This;
typedef void (*Type::Method)();
Type* obj_;
Method mtd_;
Thunk(Type* obj, Method mtd) : obj_(assert_non_null(obj)), mtd_(assert_non_null(mtd)) {}
static DWORD CALLBACK thunk_proc(LPVOID param)
{
This* thunk = assert_non_null(reinterpret_cast<This*>(param));
thunk->play();
delete thunk;
return 0;
}
void play()
{
(obj_->*mtd_)();
}
};
///
class Greeting
{
public:
void hello();
void goodbye();
};
///
Greeting a, b;
CreateThread(Thunk<Greeting>::thunk_proc, new Thunk<Greeting>(&a, &Greeting::hello));
CreateThread(Thunk<Greeting>::thunk_proc, new Thunk<Greeting>(&b, &Greeting::goodbye));
В более общем виде — можно делать шлюз для boost::function
DWORD CALLBACK boost_function_thunk(LPVOID param)
{
boost::function0<void>* pfn = reinterpret_cast<boost::function0<void>*>(param);
(*pfn)();
delete pfn;
return 0;
}
///
CreateThread(boost_function_thunk, new boost::function0<void>(&a, &Greeting::hello));