В чем разница между функцией класса и глобальной функцией в отношении указателей на функции в C ++? Я спрашиваю, поскольку метод Windows CreateThread, похоже, не принимает функцию, в которую входит код потока, если функция является членом класса.
Я могу передать функцию (в которую входит код потока) в сообщение CreateThread, когда это глобальный метод, но как только я сделаю его членом класса, я получаю ошибку «аргумент типа [макет метода] несовместим с параметром типа LPTHREAD_START_ROUTINE «. ClassName :: * теперь находится посередине; это влияет на это?
Как это обойтись?
лямбда-выражения в C ++ 11 или boost :: bind перед этим — опубликуйте ошибочный код, и мы покажем вам, как — person Ghost schedule 14.08.2013
Сигнатура возможных потоковых функций должна быть точно согласована, Win32-API — это чистый C API, не предназначенный для работы с C ++ — классами. — person Ghost schedule 14.08.2013
@doctorlove, результат не будет совместим с указателем на функцию, взятым CreateThread
. — person Ghost schedule 14.08.2013
В C ++ 11 вы можете подумать о переходе на стандартную библиотеку потоковой передачи. Тогда это что-то вроде thread([this]{member();})
, а не тарабарщина в правильном ответе, с переносимостью в качестве бонуса. — person Ghost schedule 14.08.2013
@MikeSeymour, Хорошая мысль, я не знаю, почему это не пришло мне в голову. Я поставлю это на видное место. — person Ghost schedule 14.08.2013
Указатели на функции-члены (
DWORD(WINAPI Foo::*)(LPVOID)
) отличаются от типов указателей на функции (DWORD(WINAPI *)(LPVOID)
). Функции-члены имеют скрытый параметрthis
, вызывающий несоответствие подписи.Самый простой способ сделать это — использовать заголовок
<thread>
C ++ 11:Если вам нужно прибегнуть к
CreateThread
, используйте параметрvoid *
для передачи экземпляра:Один в вашем классе теперь может быть практически любым, каким вы хотите (например,
std::function
), и по-прежнему работать, пока он вызывается с правильными аргументами из процедуры прокси.Стоит отметить, что это также могло бы работать, если бы
proxyThreadProc
был статической функцией-членомFoo
. Иногда это хороший способ использовать частные функции-члены в таких ситуациях. — person Ghost; 14.08.2013Разве после функции extern C не должно быть символа «{» и закрывающего символа «}»? — person Ghost; 14.08.2013
@MagnusHoff, для меня это тоже ново, но прочтите это. — person Ghost; 14.08.2013
@Kevin, фигурные скобки нужны только для заключения множественных. — person Ghost; 14.08.2013
@chris О. Спасибо. Соответствующая цитата: обратите внимание, что функция обратного вызова C, реализованная в C ++, должна быть
extern "C"
. Может показаться, что она работает как статическая функция в классе, потому что статические функции класса часто используют то же соглашение о вызовах, что и функция C. Однако это ожидает своего появления ошибка (см. Комментарии ниже), поэтому, пожалуйста, не делайте этого — вместо этого используйтеextern "C"
оболочку. (Интересное обсуждение темы) — person Ghost; 14.08.2013@MagnusHoff, Да, и на самом деле, в Windows, я считаю, что вероятность того, что это когда-либо станет проблемой, мала и равна нулю (вероятно, поэтому я так долго не знал об этом), но лучше иметь более правильный код. — person Ghost; 14.08.2013
да, как сказал @chris, есть скрытый указатель на это, который будет подключен к концу параметров. когда поток выполняет это, он не знает, соответствует ли указатель в позиции последнего параметра, тогда ему не удалось восстановить кучу этой функции по завершении, поэтому запрещено использовать нестатическую функцию-член класса для управления функцией потока, за исключением глобальной функции или статической функции-члена класса.