耐心地看,包括例子,你會有收獲的!
//先熟悉一下函數指針的用法
#include <stdio.h>
int f1(int a);
int f2(int a, int b);
typedef int(*F)(); //注意形參為空,自由度大一點
typedef struct _A
{
int n;
F f;
}A;
int main()
{
A a[]={{10, f1}, {100, f2}};
printf("%d\n", a[0].f(a[0].n));
printf("%d\n", a[1].f(a[1].n, a[1].n));
system("pause");
return 0;
}
int f1(int a)
{
return a;
}
int f2(int a, int b)
{
return a+b;
}
//下面的模型我覺得挺不錯的
//*****************************************************my_struct.h
#ifndef MY_STRUCT_H
#define MY_STRUCT_H
typedef struct _my_struct
{
char *code;
int (*func1)(); //函數形參可以省略,C編譯器不檢查,增加了自由度,但是也增大了出錯幾率,要小心!!
int (*func2)();
}my_struct;
extern my_struct Code_func[]; //extern變量聲明(不是定義),所以其他文件只要包含該頭文件就可使用該全局變量,‘extern’關鍵字不能省略!!
extern int tr003(); //函數聲明,‘extern’關鍵字可省略
extern int prs003(); //函數形參可以省略,C編譯器不檢查,增加了自由度,但是也增大了出錯幾率,要小心!!
extern int tr004();
extern int prs004();
extern int tr006();
extern int prs006();
#endif
//*************************************************************var_def.c
#include "my_struct.h"
//定義並初始化了一個全局數組,添加交易直接在此處添加,並在頭文件裡面聲明對應的函數
my_struct Code_func[]=
{
{"003",tr003,prs003},
{"004",tr004,prs004},
{"006",tr006,prs006},
{NULL}
};
//********************************************************************main.c
#include "my_struct.h"
//這樣就可以直接用 Code_func 數組了
int main()
{
........
while (Code_func[i].code != NULL)
{
if (strcmp(msgHead->txCode, Code_func[i].code) == 0)
{
result1 = (Code_func[i].func1)(writer,buf,pBodyIn,iBodyNum);
//result1 = (*Code_func[i].func1)(writer,buf,pBodyIn,iBodyNum);和上面的調用沒有區別
result2 = (Code_func[i].func2)(......);
break;
}
i++;
}
.......
}
例子:《深入淺出MFC》第一章 第20頁——消息映射(Message Map)的雛形
有沒有可能把窗口函數的內容設計得更模塊化、更一般化些?下面是一種作法。請注意,
以下作法是MFC「消息映射表格」(第9章)的雛形,我所采用的結構名稱和變量名稱,
都與MFC 相同,藉此讓你先有個暖身。
首先,定義一個MSGMAP_ENTRY 結構和一個dim 宏:
struct MSGMAP_ENTRY {
UINT nMessage;
LONG (*pfn)(HWND, UINT, WPARAM, LPARAM);
};
#define dim(x) (sizeof(x) / sizeof(x[0]))
請注意MSGMAP_ENTRY 的第二元素pfn 是一個函數指針,我准備以此指針所指之函
數處理nMessage 消息。這正是對象導向觀念中把「資料」和「處理資料的方法」封裝
起來的一種具體實現,只不過我們用的不是C++ 語言。
接下來,組織兩個數組_messageEntries[ ] 和_commandEntries[ ],把程序中欲處理的消
息以及消息處理例程的關聯性建立起來:
// 消息與處理例程之對照表格
struct MSGMAP_ENTRY _messageEntries[] =
{
WM_CREATE, OnCreate,
WM_PAINT, OnPaint,
WM_SIZE, OnSize,
WM_COMMAND, OnCommand,
WM_SETFOCUS, OnSetFocus,
WM_CLOSE, OnClose,
WM_DESTROY, OnDestroy,
} ; ↑ ↑
這是消息 這是消息處理例程
//Command-ID與處理例程之對照表格
struct MSGMAP_ENTRY _commandEntries =
{
IDM_ABOUT, OnAbout,
IDM_FILEOPEN, OnFileOpen,
IDM_SAVEAS, OnSaveAs,
} ; ↑ ↑
這是WM_COMMAND消息 這是消息處理例程
//----------------------------------------------------------------------
//於是窗口函數可以這麼設計:
//----------------------------------------------------------------------
//窗口函數:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,WPARAM wParam, LPARAM lParam)
{
int i;
for(i=0; i < dim(_messageEntries); i++){ //消息對照表
if (message == _messageEntries[i].nMessage)
return((*_messageEntries[i].pfn)(hWnd, message, wParam, lParam));
}
return(DefWindowProc(hWnd, message, wParam, lParam));
}
//----------------------------------------------------------------------
// OnCommand --專門處理WM_COMMAND
//----------------------------------------------------------------------
LONG OnCommand(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int i;
for(i=0; i < dim(_commandEntries); i++) { //命令項對照表
if (LOWORD(wParam) == _commandEntries[i].nMessage)
return((*_commandEntries[i].pfn)(hWnd, message, wParam, lParam));
}
return(DefWindowProc(hWnd, message, wParam, lParam));
}
//-------------------------------------消息處理函數-------------------
LONG OnCreate(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
...
}
LONG OnAbout(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
...
}
......
//----------------------------------------------------------------------
這麼一來,WndProc 和OnCommand 永遠不必改變,每有新要處理的消息,只要在
_messageEntries[ ] 和_commandEntries[ ] 兩個數組中加上新元素,並針對新消息撰寫新
的處理例程即可。
這種觀念以及作法就是MFC 的Message Map 的雛形。MFC 把其中的動作包裝得更好
更精致(當然因此也就更復雜得多),成為一張龐大的消息地圖;程序一旦獲得消息,
就可以按圖上溯,直到被處理為止。我將在第3章簡單仿真MFC 的Message Map,並在
第9章「消息映射與繞行」中詳細探索其完整內容。
PS:《深入淺出MFC》(侯捷著) 是一本非常出色的書!
非常喜歡侯捷的一句話:程序設計領域裡,每一個人都想飛。但是,還沒學會走之前,連跑都別想!