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;
}

猜你喜欢

转载自blog.csdn.net/SongXJ_01/article/details/104933496