Des fonctions virtuelles et statiques

Des fonctions virtuelles et statiques - C++ - Programmation

Marsh Posté le 28-11-2002 à 17:47:07    

TOc-toc-toc, Y'a t'il des pros de la POO ??
 
Salut à tous,  
Je lutte depuis qq temps sur un bête code en C++ (presque) à 2 balles:  
Voilà, j'ai voulu implémenter une classe du genre Cwnd ( les accros MFC reconnaitront), c'est une classe pour gérer les fenetres, mais, je galère pour pourvoir la dériver. En effet, il est nécessaire de passer un ds la fonction RegisterClassEx un pointeur sur ma fonction de gestion des messages la fameuse WndProc.
CE qui m'oblige à la déclarer static.
Mais après, celle-ci ne peut appeler que des fonctions static et là triple zob! Je ne peux plus me servir de fonctions virtuelles ! ( ça marche plus à la compilation..)
 
J'ai essayé d'utiliser des variables membres pointeurs sur fonctions auxquelles j'assigne l'adresse de mes fonctions virtuelles, mais ça ne marche toujours pas à la compilation (pb de portée ?)!
Si ça interresse quelqu'un je posterai un bout de mon code ( c'est peut-être pas clair..)
Bref, ma question est:
Comment appeller des fonctions virtuelles depuis une fonction statique ?
 
PS: Faites-vite, je sens que je vais jeter le PC par la fentre !!!

Reply

Marsh Posté le 28-11-2002 à 17:47:07   

Reply

Marsh Posté le 28-11-2002 à 18:02:10    

j'aurai tendance à dire que c normal.
Poste ton code pr vérifier stp...

Reply

Marsh Posté le 29-11-2002 à 04:54:11    

Il faut un moyen d'associer le handle de fenêtre hwnd reçu par la WNDPROC au pointeur this de la classe ayant généré cette fenêtre.
 
J'imagines qu'un map STL ferait l'affaire, informé à chaque construction/destruction.


Message édité par Musaran le 29-11-2002 à 04:54:35

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 29-11-2002 à 09:52:46    

J'vais passer pour un con: C'est koi un map STL ?

Reply

Marsh Posté le 29-11-2002 à 10:02:14    

Le problème est archi classique, il te faut trouver un moyen de retrouver la classe depuis ta fonction statique...
 
les methodes :

  • La globale: mettre un pointeur sur lma classe en global ainsi la call-back la retrouve c'est ni beau, ni reentrant, ni thread-safe
  • void * data : la fonction qui prend la call-back prend avec un pointeur void* dont elle ne fait rien sinon le repasser à la call-back à l'execution (souvent dans les solveurs Mathematiques) dans ce cas passer la classe dans le call-back


Je n'en connais pas d'autres...
 
Bien sur la permiere methode peut-etre ameliorée en utilisant un tableaux de poinbteurs, voir une map : http://www.roguewave.com/support/d [...] f/map.html

Reply

Marsh Posté le 29-11-2002 à 11:54:43    

Bon, finalement, j'ai trouvé une solution pour mon histoire
de fonction virtuelles dans une fonction statique.
Dans le présent cas, j'utilise GWL_USERDATA, mais bon, j'aurais pas tjrs ça sous la main !!
C'est pas grave, j'ai pigé le mécanisme !
Merci à ceux qui m'ont aidé!
Et voici le code qui posait problème:  
 
 
 
#define CWINDOW_CLASSNAME  "CWindowClass"// Classe de fenetre CWindow class CWindow  
{
public:
HWND hWnd;
int ProcessMsg();
virtual BOOL Create(LPCTSTR lpszWindowName = "", DWORD dwX = CW_USEDEFAULT, DWORD dwY = CW_USEDEFAULT, DWORD dwWidth = CW_USEDEFAULT, DWORD dwHeight = CW_USEDEFAULT, LPCTSTR lpszClassName = CWINDOW_CLASSNAME, DWORD dwExStyle = 0, DWORD dwStyle = (WS_OVERLAPPEDWINDOW | WS_VISIBLE));// Cree la fenetre
CWindow();
virtual ~CWindow(); private:
// il faut définir la fonction comme static pour pouvoir la passer en tant que pointeur
static LRESULT CALLBACK MyWindowProc(  HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); // Les hanlers pour chaque evt ds ma classe
virtual void OnKeyDown(int nVirtKey, long lKeyData);
}; // Dérivée de la classe CWindow
class CxDialog : public CWindow
{
public:
CxDialog();
virtual ~CxDialog();
protected:
// Un handler spécial pour cette classe
// Une fonction virtuelle car appelée depuis MyWindowProc
virtual void OnKeyDown(int nVirtKey, long lKeyData);
}; BOOL CWindow::Create(LPCTSTR lpszWindowName,  DWORD dwX, DWORD dwY, DWORD dwWidth, DWORD dwHeight, LPCTSTR lpszClassName, DWORD dwExStyle, DWORD dwStyle)
{
WNDCLASSEX winclass;
DWORD resu = 0; // Initialiser la classe de fenetre
ZeroMemory(&winclass, sizeof(winclass));
winclass.cbSize = sizeof(winclass);
winclass.style = 0;
winclass.lpszMenuName = NULL;
winclass.lpszClassName = lpszClassName;
winclass.cbWndExtra = NULL;
winclass.cbClsExtra = NULL;
winclass.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH);
winclass.hInstance = GetModuleHandle(NULL);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 
// Ici, on est obligé de passer un pointeur sur une fonction
// statique ( puisque pour obtenir un pointeur, il faut qu'elle soit
// statique ...CQFD)
// Et ce, même si on passe par un variable ( qu'il faudra bien
// initialiser => Idem!)
winclass.lpfnWndProc = (WNDPROC) MyWindowProc; resu = RegisterClassEx(&winclass); // Créer la fenetre
hWnd = CreateWindowEx( dwExStyle, lpszClassName,
lpszWindowName,
dwStyle, dwX, dwY, dwWidth, dwHeight,
NULL, NULL,
GetModuleHandle(NULL),
NULL);
 
// On enregistre l'instance de classe associée à cette fenetre
// sert ds MyWindowProc
SetWindowLong(hWnd, GWL_USERDATA, (LONG) this); return TRUE;
} LRESULT CALLBACK CWindow:: MyWindowProc(  HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{ // La solution trouvée ds le source de VNC d'AT&T
// "This is a static method, so we don't know which instantiation we're
// dealing with. We use Allen Hadden's (ahadden@taratec.com) suggestion
// from a newsgroup to get the pseudo-this."
CWindow *CurrentObject = (CWindow *)GetWindowLong( hwnd, GWL_USERDATA);
if(!CurrentObject)
{return DefWindowProc(hwnd, uMsg,wParam,lParam);}// trop tôt! // Sinon, comment appeller les fonctions virtuelles
// d'une classe depuis une fonction statique ?
// Faut-il tjrs récupérer un pointeur sur l'instance ? switch(uMsg){
case WM_QUIT:
case WM_CLOSE:
PostQuitMessage(0);
return FALSE;
break;
 
 
case WM_KEYDOWN:// L'appui sur échap ferme la fenetre
CurrentObject->OnKeyDown((int)wParam, lParam);
return FALSE;
break;
}
 
// Le reste c'est windows qui s'en charge
return DefWindowProc(hwnd, uMsg,wParam,lParam) ; } int CWindow::ProcessMsg()
{
/*
 *Un banale pompe à messages ...
 */
} void CWindow::OnKeyDown(int nVirtKey, long lKeyData)
{switch(nVirtKey){
case VK_ESCAPE:// ds un cas on sort
PostQuitMessage(0);
break;
}
} void CxDialog::OnKeyDown(int nVirtKey, long lKeyData)
{switch(nVirtKey){
case VK_ESCAPE:// ds l'autre on affiche une msgbox
MessageBox(NULL, "CxDialog::OnKeyDown","",0);
break;
}
} Tout ça parce que j'aime pas les MFC !!!

Reply

Marsh Posté le 29-11-2002 à 11:58:06    

Euh BENB ... C'est un problème archi-classique ?
Vraiment ?
J'ai honte .... ( je code en C depuis + de 7 ans ...)

Reply

Marsh Posté le 29-11-2002 à 13:09:26    

Stfou a écrit a écrit :

Euh BENB ... C'est un problème archi-classique ?
Vraiment ?
J'ai honte .... ( je code en C depuis + de 7 ans ...)
 




 
ben ouais [:spamafote] (obj + fonction callback)


Message édité par chrisbk le 29-11-2002 à 13:09:40
Reply

Marsh Posté le 29-11-2002 à 13:37:11    

Stfou a écrit a écrit :

Euh BENB ... C'est un problème archi-classique ?
Vraiment ?
J'ai honte .... ( je code en C depuis + de 7 ans ...)
 




 
Je fais bcp de calcul numerique...
Bcp de solveurs fonctionnent comme cela avec une call-back, or la fonction a resoudre depends toujours de parametres physiques...
 
Donc c'est arch-classque... ...pour moi en tout cas... ;)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed