C语言实现面向对象和封装

前言

今天的Windows应用开发课上,教授让我们用纯C语言实现面向对象的开发和封装。如果用C++那实现面向对象是轻而易举,但是用纯C的话,emmm想想就头大,光一个字符串的操作就搞了半天,和C++比起来,C语言真的太“基础”了,几乎所有的方法都要自己写。
这个代码我硬钢了两天,一共写了500行左右,收获还是蛮大的,算是比较完善的将方法封装了起来。

代码要求

  • 用纯C实现面向对象编程
  • 包含基类和一层子类,子类及其继承的方法由用户自己设定,但要有接口
  • 所有的方法都要进行封装,不能显示出来参数类型

代码实现结构

首先,为了实现封装而且不显示参数类型,将所有的参数都设置为int类型(包括结构体),通过int转换为各种指针类型,再由指针析取为实际类型进行参数的操作

所有的方法封装到WinProc接口中,通过其中的msg参数辨别进行哪一个方法的调用。另外,为了实现基类和子类接口的统一,另外加了一个CallProc接口,实现分配基类和子类的操作函数。

//封装的窗口操作函数
int WinProc(int win, int msg, int param1, int param2) {
    switch (msg){
    case MOVE: move(win, param1, param2); break;
    case SET_POSITION:  SetPosition(win, param1, param2); break;
    case GET_POSITION: {Pos p = GetPosition(win);   return (int)&p; }break;
    
    case SET_SIZE: SetSize(win, param1, param2); break;
    case GET_SIZE: {WinSize p = GetSize(win);   return (int)&p; }break;
    
    case SET_TITLE: SetTitle(win, (char*)param1); break;
    case GET_TITLE: return (int)GetTitle(win); break;
    
    case PRINTWINDOW: PrintWindow(win); break;
    
    case CONSTRUCT: return ConstructBase(win); break;
    case DESTRACT: DestroyWindow(win); break;
    
    case MEM_GET: return getMem(win, param1); break;
    case MEM_SET: setMem(win, param1, param2); break;
    
    case STATIC_GET: return getStatic(win, param1, param2); break;
    case STATIC_SET: setStatic(win, param1, param2); break;
    
    case COPY: return CopyWindow(win); break;
    default:    break;
    }
}

//分配基类和子类操作函数的调用接口
int CallProc(int win, int msg, int param1, int param2) {
    for (int i = 0; i < objectIndex; ++i) { //遍历所有实例
        if (objects[i].object == win) {     //找到这个实例
            if (objects[i].index == -1)     //如果是基类,则返回基类对应的操作函数
                return WinProc(win, msg, param1, param2);
            return subclasses[objects[i].index].pFn(win, msg, param1, param2);  //如果是子类,则返回子类对应的操作函数
        }
    }
    return 0;
}

该项目建立了一个基类window,其中包括一组窗口的位置信息Pos包含xy,和窗口的大小信息WinSize包含widthheight,还有窗口的名字title,是一个 char[200] 数组(怀念C++的string啊~~~~)

//位置结构体,包含(x,y)
typedef struct Pos {    
    int x, y;
};

//窗口大小结构体,包含宽、高
typedef struct WinSize {    
    int width, height;
};

//基类
struct window {
    Pos pos;
    WinSize size;
    char title[200];
};

在这个基类的基础上,用户可以通过RegisterClass()接口创建子类,子类可以包含附加变量和static变量,在创建时要说明变量类型(即变量所占用字节数)用于后期分配内存。

//创建一个新的子类
void RegisterClass(char* name, int data, int staticdata, int (*fn)(int, int, int, int)) {
    strcpy(subclasses[subClassIndex].Name, name);
    subclasses[subClassIndex].Bytes = data;
    subclasses[subClassIndex].StaticBytes = staticdata;
    subclasses[subClassIndex].pStatic = (char*)malloc(staticdata);  //开辟子类的static内存空间
    subclasses[subClassIndex].pFn = fn;
    //初始化静态变量
    int type;
    switch (staticdata) {
    case 4: *(int*)subclasses[subClassIndex].pStatic = 0; break;        //int初始化为0
    case 1: *(char*)subclasses[subClassIndex].pStatic = 'a'; break;     //char初始化为‘a’
    default:strcpy(subclasses[subClassIndex].pStatic, "");  break;      //string初始化为空串
    }
    subClassIndex++;    //子类的个数增加1
}

为了储存子类和实例,分别又建立了两个结构体SubClassObject,并分别开辟了两个数组来储存子类和实例。SubClass结构体中包含了子类的名字、子类附加变量增加字节数、子类static变量增加字节数、指向static变量的指针和一个函数指针(这里类似C++中函数的重载)。Object结构体中储存了类的实例,其中包含了指向类的实例的指针和一个表示子类类型的指针。

//子类
struct SubClass {
    char Name[200]; //子类名字
    int Bytes;      //子类附加变量增加字节数
    int StaticBytes;    //子类static变量增加字节数
    char* pStatic;      //子类static的指针
    int (*pFn)(int win, int msg, int param1, int param2);   //子类的方法函数
}subclasses[50];
int subClassIndex = 0;

//获取当前创建的子类总数
int getSubClassNum() { return subClassIndex; }

//所有类的实例
struct Object {
    int object; //类的实例
    int index;  //若为基类的实例则是-1,若为子类的实例则为其在subclasses里面对应子类的下标
}objects[100];
int objectIndex = 0;    //实例的个数

//获取当前创建的实例总数
int getObjNum() { return objectIndex; }

关键细节

  1. void* p = malloc(sizeof(window) + subclasses[objects[i].index].Bytes); 开辟子类实例的内存空间。子类实例不仅要开辟基类变量所包含的内存空间(实现继承),还要有自己的内存空间。【注意:子类的实例不包含子类变量的static静态变量的内存空间。因为静态变量是属于子类的,在定义子类的时候已经开辟,不属于子类的实例。】
  2. window* p = (window*)win; 因为在项目中所有的参数传递都是用指针以int类型进行传递,这个语句可以将int(实际上是指针)转换为window类型。其他类型的转换同理。
  3. char* p = (char*)win + sizeof(window); 这一步操作本质上只是一个指针的跨越,但是它实现了对子类附加变量的指针定位。

不足之处

代码中有一个暂未解决的bug,本来说是想实现构造函数和析构函数,但在 delete 清除实例内存的时候出现了一点问题,总是报内存泄漏的错误,希望路过的大佬可以帮忙完善一下,不尽感激。

//删除窗口(暂未通过调试)
void DestroyWindow(int win) {
    if (!win) {
        delete (window*)win;
    }
}

完整代码

完整的window.cpp如下:
//Author:SongXingJian 
#include "stdio.h"
#include "string.h"
#include "malloc.h"
#include "window.h"

//位置结构体,包含(x,y)
typedef struct Pos {    
    int x, y;
};

//窗口大小结构体,包含宽、高
typedef struct WinSize {    
    int width, height;
};

//基类
struct window {
    Pos pos;
    WinSize size;
    char title[200];
};

//子类
struct SubClass {
    char Name[200]; //子类名字
    int Bytes;      //子类附加变量增加字节数
    int StaticBytes;    //子类static变量增加字节数
    char* pStatic;      //子类static的指针
    int (*pFn)(int win, int msg, int param1, int param2);   //子类的方法函数
}subclasses[50];
int subClassIndex = 0;

//获取当前创建的子类总数
int getSubClassNum() { return subClassIndex; }

//所有类的实例
struct Object {
    int object; //类的实例
    int index;  //若为基类的实例则是-1,若为子类的实例则为其在subclasses里面对应子类的下标
}objects[100];
int objectIndex = 0;    //实例的个数

//获取当前创建的实例总数
int getObjNum() { return objectIndex; }

//创建一个新的子类
void RegisterClass(char* name, int data, int staticdata, int (*fn)(int, int, int, int)) {
    strcpy(subclasses[subClassIndex].Name, name);
    subclasses[subClassIndex].Bytes = data;
    subclasses[subClassIndex].StaticBytes = staticdata;
    subclasses[subClassIndex].pStatic = (char*)malloc(staticdata);  //开辟子类的static内存空间
    subclasses[subClassIndex].pFn = fn;
    //初始化静态变量
    int type;
    switch (staticdata) {
    case 4: *(int*)subclasses[subClassIndex].pStatic = 0; break;        //int初始化为0
    case 1: *(char*)subclasses[subClassIndex].pStatic = 'a'; break;     //char初始化为‘a’
    default:strcpy(subclasses[subClassIndex].pStatic, "");  break;      //string初始化为空串
    }
    subClassIndex++;    //子类的个数增加1
}

//移动窗口
void move(int win, int deltaX, int deltaY) {
    window* p = (window*)win;   //将任意封装类型强制转化为所需要的内容
    p->pos.x += deltaX;
    p->pos.y += deltaY;
}

//设置窗口位置
void SetPosition(int win, int x, int y) {
    window* p = (window*)win;
    p->pos.x = x;
    p->pos.y = y;
}

//返回窗口位置
Pos GetPosition(int win) {
    window* p = (window*)win;
    Pos win_pos;
    win_pos.x = p->pos.x;
    win_pos.y = p->pos.y;
    return win_pos;
}

//设置窗口宽和高
void SetSize(int win, int width, int height) {
    window* p = (window*)win;
    p->size.width = width;
    p->size.height = height;
}

//获取窗口宽和高
WinSize GetSize(int win) {
    window* p = (window*)win;
    WinSize win_size;
    win_size.width = p->size.width;
    win_size.height = p->size.height;
    return win_size;
}

//设置窗口title
void SetTitle(int win, char* newTitle) {
    window* p = (window*)win;
    //p->title = newTitle;
    strcpy(p->title, newTitle);
}

//返回窗口title
char* GetTitle(int win) {
    window* p = (window*)win;
    return p->title;
}

//创建Window,参数是子类名字,创建基类则传入0
int CreateWindow(char* name) {
    int new_win = 0;
    if (!name) {    //创建基类实例
        window* p = (window*)malloc(sizeof(window));
        WinProc((int)p, CONSTRUCT, 0, 0);   //初始化基类变量
        new_win = (int)p;
        objects[objectIndex].object = new_win;
        objects[objectIndex].index = -1;    //基类的下标设置为-1
        objectIndex++;  //实例数+1
    }
    else {  //创建子类实例
        for (int j = 0; j < subClassIndex; ++j) {
            if (!strcmp(name, subclasses[j].Name)) {    //如果name相等,即找到了subclasses的位置
                void* p = malloc(sizeof(window) + subclasses[j].Bytes); //开辟该子类实例所需空间
                WinProc((int)p, CONSTRUCT, 0, 0);   //初始化基类变量
                new_win = (int)p;
                objects[objectIndex].object = new_win;
                objects[objectIndex].index = j; //下标设置为在subclasses里面相同子类的下标
                objectIndex++;  //实例数+1
                break;
            }
        }
    }   
    return new_win;
}

//基类的构造函数,初始化基类变量
int ConstructBase(int win) {
    window* p = (window*)win;
    strcpy(p->title, "");
    p->pos.x = 0;
    p->pos.y = 0;
    p->size.width = 0;
    p->size.height = 0;
    return (int)p;
}

//拷贝并创建实例
int CopyWindow(int win) {
    int new_win;
    for (int i = 0; i < objectIndex; ++i) { //遍历所有实例
        if (objects[i].object == win) {     //找到这个实例
            if (objects[i].index != -1) {   //如果是子类
                void* p = malloc(sizeof(window) + subclasses[objects[i].index].Bytes);  //开辟该子类实例所需空间               
                new_win = (int)p;
                WinProc(new_win, CONSTRUCT, 0, 0);
                //确定子类附加变量的参数类型
                int type_mem;
                if (subclasses[objects[i].index].Bytes == 4)    type_mem = SUB_INT;
                else if (subclasses[objects[i].index].Bytes == 1)   type_mem = SUB_CHAR;
                else type_mem = SUB_STRING;
                //复制子类附加变量
                WinProc(new_win, MEM_SET, type_mem, WinProc(objects[i].object, MEM_GET, type_mem, 0));
                objects[objectIndex].object = new_win;
                objects[objectIndex].index = objects[i].index;  //下标设置为在subclasses里面相同子类的下标
                objectIndex++;  //实例数+1
            }
            else {  //如果是基类
                window* p = (window*)malloc(sizeof(window));
                new_win = (int)p;
                WinProc(new_win, CONSTRUCT, 0, 0);
                objects[objectIndex].object = new_win;
                objects[objectIndex].index = -1;    //基类的下标设置为-1
                objectIndex++;  //实例数+1
            }
            //复制基类变量
            WinProc(new_win, SET_TITLE, WinProc(objects[i].object, GET_TITLE, 0, 0), 0);    //赋值新实例的title
            Pos w_pos = *(Pos*)WinProc(objects[i].object, GET_POSITION, 0, 0);  //获取被复制实例的pos
            WinProc(new_win, SET_POSITION, w_pos.x, w_pos.y);   //赋值新实例的pos
            WinSize w_size = *(WinSize*)WinProc(objects[i].object, GET_SIZE, 0, 0); //获取被复制实例的size
            WinProc(new_win, SET_SIZE, w_size.width, w_size.height);    //赋值新实例的size

            return new_win;
        }
    }
}

//删除窗口(暂未通过调试)
void DestroyWindow(int win) {
    if (!win) {
        delete (window*)win;
    }
}

//打印窗口的所有属性
void PrintWindow(int win) {
    window* p = (window*)win;
    printf_s("\n================ %s ================\nPosition: (%d, %d)\nWidth: %d\tHeight: %d\n", p->title, p->pos.x, p->pos.y, p->size.width, p->size.height);
}

//获得子类中的变量
int getMem(int win, int  sub_type) {
    char* p = (char*)win + sizeof(window);  //指针p跨越基类内存,指向子类附加内存
    if (sub_type == SUB_INT)            //子类附加的数据是int
        return *(int*)p;
    else if (sub_type == SUB_CHAR)  //子类附加的数据是char
        return *p;
    else if (sub_type == SUB_STRING)    //子类附加的数据是字符串
        return (int)p;
}

//设置子类中的变量
void setMem(int win, int  sub_type, int param2) {
    char* p = (char*)win + sizeof(window);  //指针p跨越基类内存,指向子类附加内存
    if (sub_type == SUB_INT)    //子类附加的数据是int
        *(int*)p = param2;
    else if (sub_type == SUB_CHAR)  //子类附加的数据是char
        *p = param2;
    else if (sub_type == SUB_STRING)    //子类附加的数据是字符串
        strcpy(p, (char*)param2);
}

//获得子类中的static变量
int getStatic(int win, int  sub_type, int param2) {
    char* p = 0;
    for (int i = 0; i < objectIndex; ++i) { //遍历所有实例
        if (objects[i].object == win) {     //找到这个实例
            if (objects[i].index != -1)     //如果不是基类
                p = subclasses[objects[i].index].pStatic;
            break;
        }
    }
    if (sub_type == SUB_INT)    //子类static变量是int
        return *(int*)p;
    else if (sub_type == SUB_CHAR)  //子类static变量是char
        return *p;
    else if (sub_type == SUB_STRING)    //子类static变量是字符串
        return (int)p;
}

//设置子类的static变量
void setStatic(int win, int  sub_type, int param2) {
    char* p = 0;
    for (int i = 0; i < objectIndex; ++i) { //遍历所有实例
        if (objects[i].object == win) {     //找到这个实例对应的子类
            if (objects[i].index != -1) {
                p = subclasses[objects[i].index].pStatic;
                if (sub_type == SUB_INT)
                    *(int*)p = param2;
                else if (sub_type == SUB_CHAR)
                    *p = param2;
                else if (sub_type == SUB_STRING) 
                    strcpy(p, (char*)param2);
                break;
            }
        }
    }

}

//封装的窗口操作函数
int WinProc(int win, int msg, int param1, int param2) {
    switch (msg){
    case MOVE: move(win, param1, param2); break;
    case SET_POSITION:  SetPosition(win, param1, param2); break;
    case GET_POSITION: {Pos p = GetPosition(win);   return (int)&p; }break;
    
    case SET_SIZE: SetSize(win, param1, param2); break;
    case GET_SIZE: {WinSize p = GetSize(win);   return (int)&p; }break;
    
    case SET_TITLE: SetTitle(win, (char*)param1); break;
    case GET_TITLE: return (int)GetTitle(win); break;
    
    case PRINTWINDOW: PrintWindow(win); break;
    
    case CONSTRUCT: return ConstructBase(win); break;
    case DESTRACT: DestroyWindow(win); break;
    
    case MEM_GET: return getMem(win, param1); break;
    case MEM_SET: setMem(win, param1, param2); break;
    
    case STATIC_GET: return getStatic(win, param1, param2); break;
    case STATIC_SET: setStatic(win, param1, param2); break;
    
    case COPY: return CopyWindow(win); break;
    default:    break;
    }
}

//分配基类和子类操作函数的调用接口
int CallProc(int win, int msg, int param1, int param2) {
    for (int i = 0; i < objectIndex; ++i) { //遍历所有实例
        if (objects[i].object == win) {     //找到这个实例
            if (objects[i].index == -1)     //如果是基类,则返回基类对应的操作函数
                return WinProc(win, msg, param1, param2);
            return subclasses[objects[i].index].pFn(win, msg, param1, param2);  //如果是子类,则返回子类对应的操作函数
        }
    }
    return 0;
}
完整的window.h如下:
//Author:SongXingJian

#define MOVE 1
#define SET_POSITION 2
#define GET_POSITION 3
#define SET_SIZE 4
#define GET_SIZE 5
#define SET_TITLE 6
#define GET_TITLE 7
#define PRINTWINDOW 8

#define CONSTRUCT 9
#define DESTRACT 10     //暂未通过调试

#define MEM_GET 11
#define MEM_SET 12

#define STATIC_GET 13
#define STATIC_SET 14

#define SUB_INT 15
#define SUB_CHAR 16
#define SUB_STRING 17

#define COPY 18


int getSubClassNum();   //获取当前创建的子类总数
int getObjNum();        //获取当前创建的实例总数
int CreateWindow(char* name);   //创建实例,参数是子类名字,基类则传入0
int WinProc(int win, int msg, int param1, int param2);      //SDK整体封装
int CallProc(int win, int msg, int param1, int param2);     //多态
void RegisterClass(char* name, int data, int staticdata, int (*fn)(int, int, int, int));    //定义一个新的子类


/*  封装过程
//void move(window* win, int deltaX, int deltaY);
//void move(void* win, int deltaX, int deltaY);
void move(int win, int deltaX, int deltaY); //对外提供接口
struct Pos GetPosition(int win);
void Size(int win, int newX, int newY);
void SetWindowText(int win, char* newTitle);
char* GetWindowText(int win);
*/
完整的main_test.cpp(主函数)如下:
//Author:SongXingJian
#include "window.h"
#include "stdio.h"

//win_num子类的函数
int sub_window_num(int win, int msg, int param1, int param2) {
    switch (msg){
        //子类构造函数,创建一个子类
    case CONSTRUCT: {   
        int w = CreateWindow((char*)win);
        WinProc(w, SET_TITLE, param1, 0);   //初始化title
        WinProc(w, MEM_SET, SUB_INT, 0);    //初始化子类实例附加变量为0
        return w;
    }break;
        //设置子类实例附加变量
    case MEM_SET: {
        printf("Set the num: %d ---> %d\n", WinProc(win, MEM_GET, SUB_INT, 0), param2); //展示修改前--->修改后
        WinProc(win, msg, SUB_INT, param2);
    }break;
        //获取子类实例附加变量
    case MEM_GET: {
        int p = WinProc(win, msg, SUB_INT, 0);
        printf("Num: %d\n", p);
    }break;
        //设置子类static变量
    case STATIC_SET: {
        printf("Set the static: %d ---> %d\n", WinProc(win, STATIC_GET, SUB_INT, 0), param2);   //展示修改前--->修改后
        WinProc(win, msg, SUB_INT, param2);
    }break;
        //获取子类static变量
    case STATIC_GET: {
        int p = WinProc(win, msg, SUB_INT, 0);
        printf("Static: %d\n", p);
    }break;
        //打印子类实例的所有变量
    case PRINTWINDOW: {
        WinProc(win, msg, param1, param2);
        printf("Num: %d\t\tStatic: %d\n", WinProc(win, MEM_GET, SUB_INT, 0), WinProc(win, STATIC_GET, SUB_INT, 0));
    }break;

    default:return WinProc(win, msg, param1, param2); break;
    }
}

//win_c子类的函数
int sub_window_c(int win, int msg, int param1, int param2) {
    switch (msg) {
        //子类构造函数,创建一个子类
    case CONSTRUCT: {
        int w = CreateWindow((char*)win);
        WinProc(w, SET_TITLE, param1, 0);   //初始化title
        WinProc(w, MEM_SET, SUB_CHAR, (int)'A');    //初始化子类实例附加变量为'A'
        return w;
    }break;
        //设置子类实例附加变量
    case MEM_SET: {
        printf("Set the Char: %c ---> %c\n", WinProc(win, MEM_GET, SUB_CHAR, 0), (char)param2); //展示修改前--->修改后
        WinProc(win, msg, SUB_CHAR, param2);
    }break;
        //获取子类实例附加变量
    case MEM_GET: {
        int p = WinProc(win, msg, SUB_CHAR, 0);
        printf("Char: %c\n", (char)p);
    }break;
        //设置子类static变量
    case STATIC_SET: {
        printf("Set the static: %c ---> %c\n", (char)WinProc(win, STATIC_GET, SUB_CHAR, 0), (char)param2);  //展示修改前--->修改后
        WinProc(win, msg, SUB_CHAR, param2);
    }break;
        //获取子类static变量
    case STATIC_GET: {
        int p = WinProc(win, msg, SUB_CHAR, 0);
        printf("Static: %c\n", (char)p);
    }break;
        //打印子类实例的所有变量
    case PRINTWINDOW: {
        WinProc(win, msg, param1, param2);
        printf("Char: %c\t\tStatic: %c\n", WinProc(win, MEM_GET, SUB_CHAR, 0), WinProc(win, STATIC_GET, SUB_CHAR, 0));
    }break;

    default:return WinProc(win, msg, param1, param2); break;
    }
}

int main() {
    char win_num[] = "sub_win_num";
    char win_c[] = "sub_win_c";

    char win_num_obj[] = "sub_win_num_obj";
    char win_c_obj[] = "sub_win_c_obj";
    char win_base_obj[] = "base_win_obj";
    
    /****************** 创建win_num子类 ******************/
    RegisterClass(win_num, sizeof(int), sizeof(int), sub_window_num);
    //int sub_w = CreateWindow(win_num);
    int sub_w = sub_window_num((int)win_num, CONSTRUCT, (int)win_num_obj, 0);   // 构造函数,可以创建实例,并初始化title、基类变量和实例附加变量 
    CallProc(sub_w, MEM_SET, SUB_INT, 5);       //设置实例的子类附加变量
    CallProc(sub_w, MEM_GET, SUB_INT, 0);
    CallProc(sub_w, STATIC_SET, SUB_INT, 3);    //设置实例所属子类static变量
    CallProc(sub_w, STATIC_GET, SUB_INT, 0);
    CallProc(sub_w, PRINTWINDOW, 0, 0);         //打印窗口属性
    //复制这个实例
    int sub_w_copy = CallProc(sub_w, COPY, 0, 0);
    CallProc(sub_w_copy, PRINTWINDOW, 0, 0);    //打印窗口属性
    //验证子类static变量的性质
    printf("\n\n****** 验证子类static变量的性质 ******\n");
    CallProc(sub_w_copy, STATIC_SET, SUB_INT, 100); //通过复制的实例修改静态变量
    CallProc(sub_w, STATIC_GET, SUB_INT, 0);        //通过另一个实例调用
    printf("\n****** The total number of Objects: %d ******\n\n", getObjNum());


    /****************** 创建win_c子类 ******************/
    RegisterClass(win_c, sizeof(char), sizeof(char), sub_window_c);
    int sub_w_c = sub_window_c((int)win_c, CONSTRUCT, (int)win_c_obj, 0);   // 构造函数,可以创建实例,并初始化title、基类变量和实例附加变量 
    CallProc(sub_w_c, MEM_SET, SUB_CHAR, (int)'B');     //设置实例的子类附加变量
    CallProc(sub_w_c, MEM_GET, SUB_CHAR, 0);
    CallProc(sub_w_c, STATIC_SET, SUB_CHAR, (int)'S');  //设置实例所属子类static变量
    CallProc(sub_w_c, STATIC_GET, SUB_CHAR, 0);
    CallProc(sub_w_c, PRINTWINDOW, 0, 0);               //打印窗口属性
    //复制这个实例
    int sub_w_c_copy = CallProc(sub_w_c, COPY, 0, 0);
    CallProc(sub_w_c_copy, PRINTWINDOW, 0, 0);
    printf("\n\n****** The total number of Objects: %d ******\n\n", getObjNum());
    printf("\n****** The total number of SubClasses: %d ******\n\n", getSubClassNum());


    /****************** 创建基类 ******************/
    int base_w = CreateWindow(0);
    CallProc(base_w, PRINTWINDOW, 0, 0);    //打印初始化的基类
    CallProc(base_w, SET_TITLE, (int)win_base_obj, 0);  //窗口重命名
    CallProc(base_w, SET_POSITION, 3, 4);   //设置窗口位置
    CallProc(base_w, MOVE, 2, 2);           //移动窗口
    CallProc(base_w, SET_SIZE, 5, 5);       //设置窗口大小
    CallProc(base_w, PRINTWINDOW, 0, 0);    //打印窗口属性
    printf("\n****** The total number of Objects: %d ******\n\n", getObjNum());

    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容