看了lighttpd中的fdevent的实现过程有些巧妙,写个例子模拟它的的实现:
虚基类是fdos(os操作系统,fd是随便加的没什么意义),它有三个派生类分别是:windows, linux, mac,
它们的都有的public方法是:open, close, playgame。
/// fdos.h #ifndef FDOS_H_INCLUDED #define FDOS_H_INCLUDED typedef enum { OS_UNSET = -1, OS_WINDOWS, OS_LINUX, OS_MAC }fd_type; typedef struct fdos { fd_type type; int maxfds; int (*open)(struct fdos *os); void (*close)(struct fdos *os); void (*playgame)(struct fdos *os, char *name); }fdos; // public fdos* fdos_init(fd_type type, int maxfds); void fdos_free(fdos *os); int fdos_open(fdos *os); void fdos_close(fdos *os); void fdos_playgame(fdos *os, char *name); // private int fdos_windows_init(fdos *os); int fdos_linux_init(fdos *os); int fdos_mac_init(fdos *os); #endif // FDOS_H_INCLUDED
/// fdos.cpp #include "fdos.h" #include <stdio.h> #include <stdlib.h> fdos* fdos_init(fd_type type, int maxfds) { fdos *os; os = (fdos*)malloc(sizeof(*os)); os->maxfds = maxfds; switch (type) { case OS_WINDOWS: if (0 != fdos_windows_init(os)) { printf("windows init fail\n"); return NULL; } return os; case OS_LINUX: if (0 != fdos_linux_init(os)) { printf("linux init fail\n"); return NULL; } return os; case OS_MAC: if (0 != fdos_mac_init(os)) { printf("mac init fail\n"); return NULL; } return os; case OS_UNSET: break; } printf("fdos init fail\n"); return NULL; } void fdos_free(fdos *os) { if (os) { free(os); } } int fdos_open(fdos *os) { return os->open(os); } void fdos_close(fdos *os) { return os->close(os); } void fdos_playgame(fdos *os, char *name) { return os->playgame(os, name); }
/// fdwindows.cpp #include "fdos.h" #include <stdio.h> static int fdos_windows_open(fdos *os) { printf("windows open\n"); return 0; } static void fdos_windows_close(fdos *os) { printf("windows close\n"); } static void fdos_windows_playgame(fdos *os, char *name) { printf("windows playgame: %s\n", name); } int fdos_windows_init(fdos *os) { os->type = OS_WINDOWS; // x作为宏参数,##x则表示连接宏参数 // 如果是#x, 则表示是一个字符串,如: // #define MY_CONST(x) #x // printf("%s", MY_CONST(hello)); // 输出:hello #define SET(x) \ os->x = fdos_windows_##x; // 相当于:fdos_windows_open SET(open); // 相当于:fdos_windows_close SET(close); // 相当于:fdos_windows_playgame SET(playgame); return 0; }
/// fdlinux.cpp #include "fdos.h" #include <stdio.h> static int fdos_linux_open(fdos *os) { printf("linux open\n"); return 0; } static void fdos_linux_close(fdos *os) { printf("linux close\n"); } static void fdos_linux_playgame(fdos *os, char *name) { printf("linux playgame: %s\n", name); } int fdos_linux_init(fdos *os) { os->type = OS_LINUX; #define SET(x) \ os->x = fdos_linux_##x; SET(open); SET(close); SET(playgame); return 0; }
/// fdmac.cpp #include "fdos.h" #include <stdio.h> static int fdos_mac_open(fdos *os) { printf("mac open\n"); return 0; } static void fdos_mac_close(fdos *os) { printf("mac close\n"); } static void fdos_mac_playgame(fdos *os, char *name) { printf("mac playgame: %s\n", name); } int fdos_mac_init(fdos *os) { os->type = OS_MAC; #define SET(x) \ os->x = fdos_mac_##x; SET(open); SET(close); SET(playgame); return 0; }
/// main.cpp #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "fdos.h" /// test int main(void) { fdos *os = fdos_init(OS_WINDOWS, 3); fdos_open(os); fdos_playgame(os, "wow"); fdos_close(os); fdos_free(os); os = fdos_init(OS_LINUX, 3); fdos_open(os); fdos_free(os); os = fdos_init(OS_MAC, 3); fdos_playgame(os, "zx"); fdos_free(os); return 0; }