Hello,OOC World![Chap2Sec1-3][GFDL]

OOC-GCC特性介绍与使用说明

pingf posted @ Sat, 11 Jun 2011 22:47:50 -1100 in 未分类 , 3816 readers

OOC-GCC 特性介绍

•核心部分仅仅是"宏",所以编译的时候更加灵活.

•两层宏定义,底层的"宏"完全采用英文全称,表意清晰.同时严格控制每个宏的定义,尽力做到不烂用.

•对于OO的模拟有构造也有析构,宏的定义具有对称性,同时符合语言规则,如表述表示 类的"名词" + 表示方法的"动词+名词".

•类的定义多数采用全开放的形式,这也使得现在的版本和VC兼容.

•方便和C++的配合.

•相对完整的类空间与实例(对象)空间的模拟,类空间的构造和析构通过类似引用计数的方法对开发者"透明".

•相对完整的单根继承的模拟,无需的在子类的构造/析构函数中显示地调用父类的构造/析构函数.

•和主流C编译工具兼容,无论GCC或是M$的编译工具都可无warning编译通过.

    ----实际测试为GCC 32bit 4.5.2 MinGW环境以及Ubuntu环境,64bit的找别人帮忙测试过,可能会有几个关于size_t的warning

    -----微软的是编译器  32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86

    -----微软的是编译器  32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86

•提供较为便利的调试层(仅针对GCC),

    ----提供更加方便的断言宏

    ----提供针对纯C的异常捕获机制的模拟

    ----提供和堆内存分配的日志监测

    ----提供仪表函数(就是监控每一个函数的调用)日志监测

    ----提供手动调用日志监测

    ----日志输出格式较为简洁,配合addr2line及graphviz等工具可以较为方便的生成图表

•提供一些常规的函数(这一部分是独立出来的)

•文件结构较为简洁,且功能上比较独立,同时有OOCfg.h中定义了一些宏开关方便一些特性的开启与停用.

•提供独立的单文件宏OOC.h,方便Release版的使用.

•提供了一些测试用例,以及在win下配合MinGW及VC编译用的批处理,*nix的GCC使用时改一下即可

-------------------------------------------------------------------------------------------------------------------------------------

关于OOC-GCC中宏的使用

类的设计(模块化的编程应在.h文件中使用)

 
假定有一个名为"A""类"

CLASS(A){
    ......  这里为实例成员
    STATIC(A);
    ......  这里是类成员(实际结构体为struct _StA,并被重定义为StA)
};

假定有一个名为"B"的继承了上面"B""类"

CLASS_EX(A,B){
    .......
    STATIC_EX(A,B); 
    .......
};

注意继承时,前面是父类,后面是要定义的子类.

类的构造与析构(模块化的编程应在.c文件中使用)

static int A_reload(A *THIS,void *p){
        THIS->.... 这里使用第一个参数来初始化实例成员
        return 0;
}
static int A_reloadSt(StA *THIS,void *p){
        THIS->.... 这里使用第一个参数来初始化类成员
        return 0;
}
static int A_unload(A *THIS,void *p){
        THIS->.... 这里使用第一个参数来析构实例成员
        return 0;
}
ASM(A,A_reload,A_unload,A_reloadSt,NULL)
注意上面最后一个参数为类成员的析构
使用NULL是为了说明无需某个函数时,可以不设置

类的使用

普通类"A"的使用
A *a=NEW0(A);  //声明第一个A的实例时调用StA和A的构造,
               //以后再声明A的实例只调用A的构造
StA *fA=ST(a);
fA->someFunc(a,someParam);
DELETE0(a);    //销毁A的实例时调用A的析构
               //当销毁显存的最后一个A的实例时,
               //调用A和StA的构造

带有继承的类"B"的使用
B *b=NEW0(B);   //注意父类的构造会自动调用
StB *fB=ST(b);
fB->someFunc(b,someParam);
StA *fA=ST(b);
fA->someFunc(b,someParam); 使用父类的方法
DELETE0(b);  //无需知道b的具体类型时A或B,都会调用正确的析构
             //如果是A的指针,则调用A的析构,如果是B的指针则调用B和A的析构

--------------------------------------------------------------------------------------------------------------------------------------------------------

关于OOC-GCC中单根继承的说明

假设我们定义四个类,A,B,C,D,并且后面的类继承前面的类,则有


CLASS(A){
        STATIC(A);
};
static int A_reload(A *THIS,char *name){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int A_unload(A *THIS,void *PARAM){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int A_reloadSt(StA *THIS,char *name){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int A_unloadSt(StA *THIS,void *PARAM){
        printf("%s\n",__FUNCTION__);
        return 0;
}
ASM(A,A_reload,A_unload,A_reloadSt,A_unloadSt)

CLASS_EX(A,B){
        STATIC_EX(A,B);
};
static int B_reload(B *THIS,char *name){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int B_unload(B *THIS,void *PBRBM){
        printf("%s\n",__FUNCTION__);
        return 0;
}
int B_reloadSt(StB *THIS,char *name){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int B_unloadSt(StB *THIS,void *PBRBM){
        printf("%s\n",__FUNCTION__);
        return 0;
}
ASM_EX(A,B,B_reload,B_unload,B_reloadSt,B_unloadSt)

CLASS_EX(B,C){
        STATIC_EX(B,C);
};
static int C_reload(C *THIS,char *name){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int C_unload(C *THIS,void *PCRCM){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int C_reloadSt(StC *THIS,char *name){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int C_unloadSt(StC *THIS,void *PCRCM){
        printf("%s\n",__FUNCTION__);
        return 0;
}
ASM_EX(B,C,C_reload,C_unload,C_reloadSt,C_unloadSt)

CLASS_EX(C,D){
        STATIC_EX(C,D);
};
static int D_reload(D *THIS,char *name){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int D_unload(D *THIS,void *PDRDM){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int D_reloadSt(StD *THIS,char *name){
        printf("%s\n",__FUNCTION__);
        return 0;
}
static int D_unloadSt(StD *THIS,void *PDRDM){
        printf("%s\n",__FUNCTION__);
        return 0;
}
ASM_EX(C,D,D_reload,D_unload,D_reloadSt,D_unloadSt)

上面的代码再调用相关的函数是会打印出对应的__FUNCTION__,

        printf("\n*****************NEW A\n");
        A *a=NEW0(A);
        printf("\n*****************NEW B\n");
        B *b=NEW0(B);
        printf("\n*****************NEW C\n");
        C *c=NEW0(C);
        printf("\n*****************DEL C\n");
        DELETE0(c);
        printf("\n*****************DEL B\n");
        DELETE0(b);
        printf("\n*****************DEL A\n");
        DELETE0(a);
        printf("\n*****************NEW D\n");
        D *d=NEW0(D);
        printf("\n*****************DEL D\n");
        DELETE0(d);

如果像上面这样调用,则会有如下输出

*****************NEW A
A_reloadSt
A_reload

*****************NEW B
A_reload
A_reloadSt
B_reloadSt
B_reload

*****************NEW C
A_reload
B_reload
A_reloadSt
B_reloadSt
C_reloadSt
C_reload

*****************DEL C
C_unload
B_unload
A_unload
A_unloadSt
B_unloadSt
C_unloadSt

*****************DEL B
B_unload
A_unload
A_unloadSt
B_unloadSt

*****************DEL A
A_unload
A_unloadSt

*****************NEW D
A_reloadSt
A_reload
A_reloadSt
B_reloadSt
B_reload
A_reloadSt
B_reloadSt
C_reloadSt
C_reload
A_reloadSt
B_reloadSt
C_reloadSt
D_loadSt
D_load

*****************DEL D
D_unload
C_unload
B_unload
A_unload
A_unloadSt
A_unloadSt
B_unloadSt
A_unloadSt
B_unloadSt
C_unloadSt
A_unloadSt
B_unloadSt
C_unloadSt
D_unloadSt

构造的时候遵循先父再子,析构的时候遵循先子再父.

另外关于静态部分的使用,在某个类第一次使用时自动的调用静态构造

当销毁某个类的最后一个实例时自动的调用静态析构

Mike Ma said:
Mon, 13 Jun 2011 03:18:25 -1100

其实我更希望能看到OOC-GCC支持GObject~这样用GOBJ就不痛苦了。。。

PS. 在互动百科的C语言条上给你做广告了~

Avatar_small
pingf said:
Tue, 14 Jun 2011 05:04:26 -1100

@Mike Ma:谢谢宣传
GObject和这个不冲突,那个更多还是类型系统.
我这个只是完成类的设计和基本的构造和析构的自动化.

不过毕竟GObject的设计初衷和我这个考虑的东西不太一样.

单以GTypeInfo为例,如果有一个类为A
struct GTypeInfo {
/* interface types, classed types, instantiated types */
guint16 class_size;

GBaseInitFunc base_init;
GBaseFinalizeFunc base_finalize;

/* interface types, classed types, instantiated types */
GClassInitFunc class_init; //这里对应OOC-GCC 中的 iniA
GClassFinalizeFunc class_finalize; //这里对应OOC-GCC 中的 finA
gconstpointer class_data;

/* instantiated types */
guint16 instance_size;
guint16 n_preallocs;
GInstanceInitFunc instance_init;

/* value handling */
const GTypeValueTable *value_table;
};
其它的似乎没法直接对应,
比如base的用途主要是为了堆数据的[有些中文翻译成基类,有时会误导]
在OOC-GCC中没有这一块,当然如果堆数据如果是一次分配的以后不变,那么可以对应到OOC-GCC中的static区域.
主要是不知道base区域是否是每个对象共享的或是每个对象独立各自的.
.....
另外很多GObject的设计过于繁琐,不利于使用,不利于记忆,所以我就不再多说了.

如果单纯从继承来说比如一个类A要继承GTypeInstance
则有
CLASS_EX(GTypeInstance,A){
STATIC(A);
};
//注意上面的代码针对0.12以后的[目前可从SVN中获得]
STATIC部分并不继承,因为GObject貌似没有和我这个对应的static部分,即使base部分我也不敢确定

另外关于GObject类型的注册,肯定还是要额外写的代码的,因为OOC-GCC本身不涉及类型系统

Avatar_small
pingf said:
Wed, 15 Jun 2011 17:54:33 -1100

@Mike Ma:
其实你要觉的GObject痛苦的话,可以不用GObject啊
只用GLib再加上这个也是不错的,
因为一般的纯C开发搞类型系统不是很必要,主要还是方便了对高级语言的绑定.

nodejs quiz said:
Fri, 10 Nov 2017 20:25:50 -1100

This page gives you a lot of information. Thank you!

NCERT English Questi said:
Fri, 23 Sep 2022 01:17:45 -1100

Most of the candidates show interest to download NCERT English Sample Paper 2023 Class 11 to gain high score in different types of exams such as Term-1, Term-2. Most of the candidates show interest to download NCERT English Sample Paper 2023 Class 11 to gain high score in different types of exams such as Term-1, Term-2 and other types of exams. Basically for 11th standard students these exams are conducting by the Board of NCERT to check the students individual abilities. and other types of exams. NCERT English Question Paper Class 11 Basically for 11th standard students these exams are conducting by the Board of NCERT to check the students individual abilities.


Login *


loading captcha image...
(type the code from the image)
or Ctrl+Enter