2009-04-20 9 views
3

Utilisation: VS2008, Win32, C/C++Comment utiliser correctement les structures dans une classe?

J'essaye d'encapsuler toute ma fenêtre de dialogue dans une classe pour la réutilisabilité. Un peu comme un contrôle personnalisé. En faisant cela, je déplace mes fonctions séparées dans une classe. La conception de structure suivante, cependant, me pose problème, avec Visual Studio en sortie: erreur C2334 '{'.

Il s'agit d'une simple disposition de carte de message. Mais je ne peux pas sembler échapper à cette erreur C2334. :(

Voici mon extrait de code de classe.

class CScrollingListDlg 
{ 
private: 

LRESULT DoCommandMain (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam); 
LRESULT DoPaintMain (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam); 
LRESULT DoAnimationTimer (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam); 
LRESULT DoHandleTouch (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam); 
LRESULT DoDestroyMain (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam); 

// 
// message maps 
// 
// Generic defines and data types. 
struct decodeUINT { 
    UINT Code; 
    LRESULT (*Fxn)(HWND, UINT, WPARAM, LPARAM); 
}; 

struct decodeCMD { 
    UINT Code; 
    LRESULT (*Fxn)(HWND, WORD, HWND, WORD); 
}; 

// WM_Message dispatch table for MainWndProc. 

// 
// *** error C2334 '{' *** 
// 
const struct decodeUINT MainMessages[] = { 
    WM_PAINT, DoPaintMain, 
    WM_DESTROY, DoDestroyMain, 
    WM_QUIT, DoDestroyMain, 
    WM_COMMAND, DoCommandMain, 
}; 


}; 

Qu'est-ce que je manque ici?

Merci.

Répondre

5

Vous ne pouvez pas spécifier d'initialiseurs pour les membres non static de cette façon - vous devez normalement déclarer le tableau puis le peupler dans le constructeur ... Sauf que, en fait, il n'y a aucun moyen d'initialiser les tableaux membres const C++ (voir this thread).

Si vous êtes prêt à partager MainMessages entre toutes les instances de CScrollingListDlg (que je soupçonne était votre intention tout le long), vous devriez en faire static, dans ce cas, vous pouvez déclarer:

static const decodeUINT MainMessages[]; // "struct" keyword unnecessary 

dans la classe définition de CScrollingListDlg, puis le définir en dehors de la classe:

const CScrollingListDlg::decodeUINT CScrollingListDlg::MainMessages[] = { 
    WM_PAINT, DoPaintMain, 
    WM_DESTROY, DoDestroyMain, 
    WM_QUIT, DoDestroyMain, 
    WM_COMMAND, DoCommandMain, // The comma *is* allowed -- thanks Josh! 
}; 

pour que cela compiler effectivement, vous aurez besoin de faire DoPaintMain(), DoDestroyMain(), etc. static - dans l'état actuel, ce sont toutes des méthodes par objet qui prennent implicitement un pointeur this, elles ne peuvent donc pas être contenues dans un pointeur de fonction de type LRESULT (*Fxn)(HWND, UINT, WPARAM, LPARAM). (Vous pouvez les laisser comme des méthodes non statiques et changer le type de pointeur dans decodeUINT à un type pointeur à fonction membre, mais c'est probablement pas ce que vous voulez.)

[EDIT: Merci à Josh pour certains commentaires utiles!]

+1

+ 1 Battez-moi, (bien que vous ayez besoin d'ajouter [] à la définition de tableau: const CScrollingListDlg :: decodeUINT CScrollingListDlg :: MainMessages [] = {... – Eclipse

+1

La virgule superflue est autorisée (initializer-clause est définie en tant que liste d'initialisation suivie d'une virgule optionnelle) et pour une bonne raison: lorsque vous ajoutez une nouvelle ligne à une liste dans un tableau comme celui-ci ou une énumération, vous ne changez qu'une seule ligne. ll finira par changer deux lignes dans le contrôle de la source chaque fois que vous ajoutez un nouvel élément.C'est juste plus clair lorsque l'on regarde les diffs si seulement la ligne intéressante change – Eclipse

+0

@Josh: Les deux bons points ne savaient pas que la virgule est permise, Merci! –

5

Vous ne pouvez pas initialiser un membre du groupe dans une déclaration de classe. Vous doit seulement déclarer MainMessages, puis l'initialiser dans les constructeurs de la classe

Je recommande également d'utiliser std :: vector au lieu de array. la modification devient:

std::vector<decodeUINT> MainMessages; 

et dans le constructeur, utilisez la méthode std :: vector :: push_back pour insérer le contenu.

Si vous avez besoin d'accéder à la mémoire gérée par le vecteur, utilisez & MainMessages [0].

+2

+1. C'est une manière sensée de le faire si un envoi de message par objet est requis, bien que le const sur le tableau suggère que l'OP a l'intention de toujours appeler les mêmes fonctions. Dans ce cas, l'utilisation d'un membre de tableau statique est plus efficace et pratique (voir ma réponse). –

+0

D'autant que MainMessages est déclaré const, je soupçonne que le tableau statique est ce qui est nécessaire. – Eclipse

+0

Je suis d'accord avec vos commentaires.Je le ferais en tant que tableau statique, ce qui signifie qu'une méthode statique pour l'initialisation est nécessaire. –

Questions connexes