2013-10-06 4 views
0

Я создал эту учетную запись, чтобы задать вопрос, потому что я потерял прямо сейчас, и я не смог найти ответ. Я не уверен, что то, что я пытаюсь сделать, даже возможно, или, возможно, я использую неправильный подход.Хранение указателя функции как члена внутри класса

Я пишу класс оболочки стека Windows для асинхронных сокетов, в основном, поэтому мне больше не нужно писать этот код, и я пытаюсь сохранить указатель на функцию как переменную-член внутри класса netcode, которая указывает на обработчиком событий Windows, который вызван в обычный служебный насос сообщений win32 приложения, который указывает в другом месте. В принципе, я пытаюсь создать определенную программистом функцию обратного вызова, так что, когда я скомпилирую этот класс netcode в .dll, мне больше не придется его трогать.

В качестве пояснения, что я пытаюсь сделать, например, написать обработчик событий для WM_SOCKET (который является сообщением Windows, которое я определил) где-то, кроме внутри класса сетевого кода (поэтому он может быть переносимым к различным проектам win32/C++) и за пределами основного насоса сообщений win32 (поэтому мой WndProc() не становится абсолютно массивным).

Я даже не знаю, что искать, но вся информация, которую я нахожу, - это создание указателя на функцию-член или элемент-шаблон, который я не хочу.

Вот код, который я уже пытался написать (только соответствующие биты), что и дает мне проблемы. Вероятно, я, вероятно, навязываю что-то здесь.

//// Sockets.h 
class NetworkConnection 
{ 
private: 
    void (*WMSocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 

public: 
    void HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 
    void registerSocketFunction(void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam))); 
}; 

//// Sockets.cpp 
#include "Sockets.h" 

void NetworkConnection::registerSocketFunction(void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam))) 
{ 
    WMSocketFunction = SocketFunction; 
}; 

void NetworkConnection::HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    WMSocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 
} 

//// Application.cpp 
void SocketEventHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    // Do socket stuff here 
}; 

int SetupApp() 
{ 
    NetworkConnection NetConnection; 
    NetConnection.registerSocketFunction(&SocketEventHandler); 
    return 0; 
} 

LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch(msg) 
    { 

    case WM_SOCKET: 
     { 
      NetConnection.HandleEvents(hwnd, msg, wParam, lParam); 
      break; 
     } 

    case WM_DESTROY: 
     { 
      ReleaseDevices(); 
      break; 
     } 
    case WM_KEYDOWN: 
     { 
#ifdef _DEBUG 
      if (lParam == VK_ESCAPE) 
       PostQuitMessage(0); 
#endif 
     } 
    } 
    return ::DefWindowProc(hwnd, msg, wParam, lParam); 
} 

Я был бы очень благодарен за помощь, здесь. Я совершенно не понимаю, почему это не работает.

Ошибки, которые я получаю, являются:

Error 1 error C2440: '=' : cannot convert from 'void *(__cdecl *)(HWND,UINT,WPARAM,LPARAM)' to 'void (__cdecl *)(HWND,UINT,WPARAM,LPARAM)' sockets.cpp (in function registerSocketFunction) 
Error 2 error C2275: 'HWND' : illegal use of this type as an expression  sockets.cpp (in function HandleEvents) 
Error 3 error C2146: syntax error : missing ')' before identifier 'hwnd' sockets.cpp (in function HandleEvents) 
Error 4 error C2059: syntax error : ')' sockets.cpp (in function HandleEvents) 
Error 8 error C2664: 'NetworkConnection::registerSocketFunction' : cannot convert parameter 1 from 'void (__cdecl *)(HWND,UINT,WPARAM,LPARAM)' to 'void *(__cdecl *)(HWND,UINT,WPARAM,LPARAM)' application.cpp 

Если вам нужны какие-либо лучшего объяснения, потому что я, вероятно, объяснил эту проблему плохо, пожалуйста, не стесняйтесь спрашивать.

Я использую Visual Studio 2010, поэтому я не думаю, что могу использовать функции C++/11, такие как std :: function.

+0

Можете ли вы объяснить, почему вы включили тег C? –

+0

Это был один из предложенных тегов. Позвольте мне это исправить. –

ответ

2

Вы должны заключить имя указателя функции в скобках, как эти: void (*SocketFunction)(...) Так вместо ваше объявление методы:

void registerSocketFunction(void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam))); 

Вы должны написать:

void registerSocketFunction(void (*SocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)); 

перепишет Кроме того вашего метод тела к настоящему времени:

void NetworkConnection::registerSocketFunction(void (*SocketFunction)(HWND, UINT, WPARAM, LPARAM)) 
{ 
    WMSocketFunction = SocketFunction; 
}; 

Следующий Я думаю, что ваш HandleEvents еще не закончен, у вас есть синтаксическая ошибка, я думаю, вы хотели вызвать функцию за указателем.

void NetworkConnection::HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    WMSocketFunction(hwnd,msg,wParam,lParam); 
} 
+0

О, мой. Вот так! Изменить: Хит ввести преждевременно. Большое спасибо за то, что вы поймали мои ошибки! Я бы проголосовал за вас, если бы у меня была репутация. Я собирался выбросить его и попробовать другой подход: –

+0

Не следует вызывать функцию с помощью указателя, как '(* WMSocketFunction) (hwnd, msg, wParam, lParam);'? –

+0

@ g-makulik Он будет работать в обоих направлениях. Я думаю, что мой путь читается просто чище. – nio

1

Вот мои подозрения. Я думаю, что способ, которым вы объявили аргумент функции SocketFunction для registerSocketFunction, неверен.

void NetworkConnection::registerSocketFunction(void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam))) 

должно быть,

void NetworkConnection::registerSocketFunction(void (*SocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)) 

я провел аналогичное испытание на НКУ, и он бросил подобную ошибку, так что это может быть ваша проблема.

4
  1. Исключить аргументы имен из объявлении указателя функции
  2. Используйте ЬурейеЕ, чтобы сделать код чище

    typedef void(*WMSocketFunction_Ptr)(HWND, UINT, WPARAM, LPARAM); 
    
    class NetworkConnection 
    { 
    private: 
        WMSocketFunction_Ptr WMSocketFunction; 
    
    public: 
        void HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 
        void registerSocketFunction(WMSocketFunction_Ptr SocketFunction); 
    }; 
    
    void NetworkConnection::registerSocketFunction(WMSocketFunction_Ptr SocketFunction) 
    { 
        WMSocketFunction = SocketFunction; 
    }; 
    
  3. предпочитают использовать STL возможности для обнаженных указателей: std::function из boost::function

    typedef std::function<void(HWND, UINT, WPARAM, LPARAM)> WMSocketFunction_Ptr; 
    
+0

Если я могу спросить, есть ли какие-либо преимущества для использования средств STL в этом примере? Каким будет синтаксис? EDIT: Кроме того, я не думаю, что могу это использовать, поскольку Visual Studio 2010 не хватает хорошей поддержки на C++/11, верно? –

+1

std :: функция более читабельная, более типичная и, следовательно, менее подвержена ошибкам. Но главное преимущество, оно более гибкое: оно позволяет связывать не только функции, но и выражения std :: bind, объекты функций и лямбды. Если я правильно помню, VS2010 с некоторым пакетом обновления поддерживает 'std :: tr1 :: function'. Если ваш компилятор не поддерживает его, вы можете использовать boost :: function. – Drop

+0

+1 для std :: function –

Смежные вопросы