Chinaunix

标题: Coo - C语言面向对象编程 [打印本页]

作者: pan_0326    时间: 2010-06-03 10:07
标题: Coo - C语言面向对象编程
目的
----
用C语言可以方便地进行面向对象编程,可以继承、多继承、使用虚函数、基类成员
直接引用、基类整体直接引用...
实现中很少使用强制类型转换,充分利用C语言的类型检查查错。现在只在虚表初始
化中使用了强制类型转换,需要小心,以后可以改进编译器避免强制类型转换。

Compiler
--------
1. gcc
  gcc -fms-extensions
2. tcc-0.9.25.1

http://sourceforge.net/projects/coo/
email: yuanbin0@gmail.com
blog: http://blog.163.com/coo_bin/
作者: koolcoy    时间: 2010-06-03 10:27
用c++不行么?嫌c++复杂可以自己定制一个c++的子集来用啊{:3_191:}
作者: pan_0326    时间: 2010-06-03 10:39
很多程序员仍然在用C
我只是再送给他们一件趁手的兵器
举个简单例子,先看C++的:
class CBase
{
public:
    int a;
};
class CThis : public CBase
{
public:
    int b;
};
CThis t;
t.a=1;
CBase* p=&t;

下面是Coo的:
#include "coo.h"
typedef struct CBase
{
    int a;
} CBase;
typedef struct CThis
{
    EXTENDS(CBase) //继承
    int b;
} CThis;
CThis t;
t.a=1;        //基类成员直接引用
CBase* p=&t.CBase; //基类整体直接引用
作者: 没本    时间: 2010-06-03 10:46
我就不说啥了,二楼替我说了。
作者: zhujiang73    时间: 2010-06-03 10:50
回复 3# pan_0326


    EXTENDS 是如何实现的?
作者: ecjtubaowp    时间: 2010-06-03 10:55
哥们还是用C++吧。
作者: pan_0326    时间: 2010-06-03 10:55
这里C和C++不分版,Coo是提供给C程序员的
C++是很强大的语言,Coo不是来挑战的
作者: 没本    时间: 2010-06-03 11:01
只要不是内存非常局限的系统,想OO没必要坚持用C吧。如果是内存非常局限的系统,不认为OO或非OO对达成开发目标会有多大区别,个人觉得不用OO甚至还会好些。
楼主的作品定位是给那些人用的?
作者: koolcoy    时间: 2010-06-03 11:04
回复 7# pan_0326


    不是挑战的意思,而是完全没有必要。如果需要继承,多态那些,把从c++中选择一个子集就行了。况且c++兼容大部分c语言,把现有的c程序稍微修改一下就可以用c++编译器来编译。
作者: liexusong    时间: 2010-06-03 11:04
用c语言实现c++的功能还不如用c++.
作者: cookis    时间: 2010-06-03 11:04
动手了就是好的,至少人家去做了,  顶
作者: pan_0326    时间: 2010-06-03 12:17
回复 5# zhujiang73


coo.h非常简单,核心部分就下面几行

#ifndef __COO_H__
#define __COO_H__

typedef struct VTable /*root of every virtual table class*/
{
    long offset; /*servers for FREE*/
} VTable;

#define EXTENDS(s) \
    union \
    { \
        s s; \
        s; \
    };
#define VT(v) const v* vt;
#define EXTENDS2(s,v) \
    union \
    { \
        VT(v) \
        s s; \
        s; \
    };
#ifndef offsetof
#define offsetof(s,m) ((long)&((s*)0)->m)
#endif
#define SUPER(s,m,p) ((s*)((char*)(p)-offsetof(s,m)))
#define FREE(p,vt) free((char*)(p)-(vt)->offset)

#endif
作者: zhujiang73    时间: 2010-06-03 12:27
回复 12# pan_0326
  1.   union \
  2.     { \
  3.         s s; \
  4.         s; \
  5.     };
复制代码
这个看起来有点奇怪,为什么这么写?
作者: pan_0326    时间: 2010-06-03 12:35
EXTENDS(CBase)展开
union
{
    CBase CBase; //可以直接访问基类整体,成员名就是基类名,易于使用
    CBase; //可以直接访问基类成员,无名结构特点
};

CThis t;
t.a=1; //不用t.CBase.a
CBase* p=&t.CBase; //多层继承时就可以看到优点了,类似于C++中(CBase*)&t
作者: pmerofc    时间: 2010-06-03 12:50
提示: 作者被禁止或删除 内容自动屏蔽
作者: zhujiang73    时间: 2010-06-03 13:01
回复 14# pan_0326


    是这个 http://docs.sun.com/app/docs/doc/820-1214/6nctbmf3j?a=view 匿名 struct 。

    这是个办法,我认为这个比 Pervise.Zhao 的那个方案好。{:3_189:}
作者: pan_0326    时间: 2010-06-03 13:08
不错
有个问题
C++总强调自己不是C
C也一直在努力保持和C++的距离
我想知道这个东西和C++的本质区别究竟 ...
pmerofc 发表于 2010-06-03 12:50



C++包罗万象,C简单实用,都很美.但每个人总有所偏好,C语言仍有存在价值
Coo不是一种新语言,而是一个技巧,让C更容易使用面向对象的思想,几乎不用付出什么代价,
因为coo.h也简单实用.
作者: pan_0326    时间: 2010-06-04 07:37
#include "coo.h"
struct VBase;
typedef struct CBase
{
  VT(struct VBase) //虚表指针,模仿C++
  int a;
} CBase;
typedef struct VBase //基类虚表类
{
  EXTENDS(VTable) //便于FREE
  int (*GetA)(const CBase*); //虚函数
} VBase;
int CBase_GetA(const CBase* pThis)
{
  return pThis->a;
}
const VBase _VBase=
{
  0,
  CBase_GetA,
};
void CBase_CBase(CBase* pThis) //构造函数
{
  pThis->vt=&_VBase; //显式装配虚表指针
  pThis->a=0;
}

上面是Coo的虚函数例子,显式嵌入虚表指针、显式定义虚表类、显式定义虚表常量
和显式装配虚表指针。这些就是C++在背后做的事情,即便作为C++程序员都应该了
解一些这些知识,事情虽多,但从上面代码来看并不复杂,会用Coo中的虚函数,也
就掌握了C++中OO多态的实现原理。
作者: hellioncu    时间: 2010-06-04 09:08
可以作为学习用
作者: fera    时间: 2010-06-04 09:25
期待大神OwnWaterloo点评
作者: xianliang    时间: 2010-06-04 10:36
本帖最后由 xianliang 于 2010-06-04 10:38 编辑
用c语言实现c++的功能还不如用c++.
liexusong 发表于 2010-06-03 11:04



    就是,要做也做得更有特色,更有简洁明了。

    我给个不太恰当的比喻,C像半自动步枪,如AK47;C++像机关枪,自动化程度高。各有用处,无法替代。AK加个瞄准,还可以当狙击使,Irac人就是这么用的。不过不专业。
作者: pan_0326    时间: 2010-06-04 11:10
就是,要做也做得更有特色,更有简洁明了。

    我给个不太恰当的比喻,C像半自动步枪,如AK4 ...
xianliang 发表于 2010-06-04 10:36



C++还不断进化呢,为什么要求C一定要保持原状成为标本?
C语言可以通过宏获得部分template功能,现在可以通过Coo更方便的OO,这样有什么不好?
C++中不是也有一些狂热者,甚至觉得有了template可以不OO了,把OO去掉怎么样?
你看看coo.h的简单,就知道是值得的.
作者: zhaohongjian000    时间: 2010-06-04 11:32
我只说一件事,

C++一开始的面向对象就是用C的宏实现的,所以楼主只是实现了一个原始的C++。
作者: pan_0326    时间: 2010-06-04 11:45
我只说一件事,

C++一开始的面向对象就是用C的宏实现的,所以楼主只是实现了一个原始的C++。
zhaohongjian000 发表于 2010-06-04 11:32



我第一次听到这种说法,我不知道怎么用宏简单地实现同名函数
编译器用特殊的预处理程序将C++代码变成C再编译倒是最简单的方法
作者: zhaohongjian000    时间: 2010-06-04 11:49
我第一次听到这种说法,我不知道怎么用宏简单地实现同名函数
编译器用特殊的预处理程序将C++代码变成 ...
pan_0326 发表于 2010-06-04 11:45

可能我说的有误,时间太久记不清,先去吃饭,回来查查,看看是用宏还是特殊的预处理程序。基本就是这么个情况。
作者: zhaohongjian000    时间: 2010-06-04 12:23
确实是我说的有误,最初版本是使用了特殊的预处理程序,实在抱歉。

但我的基本结论不变。
作者: seecu    时间: 2010-06-04 13:03
回复 1# pan_0326


     我关心的是:与C++比有啥区别?比C++有啥优点?克服了C++的哪些不足?
作者: la.lune    时间: 2010-06-04 13:19
可以用简单的方法把OO的设计方法引入C
支持
作者: pan_0326    时间: 2010-06-04 15:46
本帖最后由 pan_0326 于 2010-06-08 16:35 编辑
回复  pan_0326


     我关心的是:与C++比有啥区别?比C++有啥优点?克服了C++的哪些不足?
seecu 发表于 2010-06-04 13:03



Coo的初衷只是让C可以OO,由于不是原生支持,当然会有不少缺点:
1. 书写仍然不能像C++那么简单,特别是虚函数
2. 无法实现同名函数
3. 无法自动构造和析构

但也不是样样不如C++
1. 嵌入基类的位置灵活,C++只能在首部
class CBase
{
public:
    double d;
};
class CThis : public CBase
{
public:
    int i;
    virtual int GetInt() const;
};
sizeof(CBase)是8,sizeof(CThis)是24,不是16.因为翻译成Coo如下:
struct VThis; //虚函数类
typedef struct CThis
{
    VT(struct VThis) //虚函数表指针
    EXTENDS(CBase) //继承
    int i;
} CThis;
但Coo由于继承的语法更灵活,所以可以这样改:
struct VThis; //虚函数类
typedef struct CThis
{
    VT(struct VThis) //虚函数表指针
    int i; //提前数据,找齐
    EXTENDS(CBase) //继承
} CThis;
基类数据嵌入可以不发生在首部,现在sizeof(CThis)是16,最紧缩状态.

2. 类数据中嵌入虚函数表指针可以有多种方法,而C++只有一种
class CBase
{
public:
    int a
    virtual int GetA() const;
};
class CInterface
{
public:
    virtual void SetA(int a);
};
class CThis : public CBase, public CInterface
{
};
sizeof(CBase)是8,sizeof(CInterface)是4,sizeof(CThis)是12.翻译成Coo如下:
struct VBase; //虚函数类
typedef struct CBase
{
    VT(struct VBase) //虚函数表指针
    int a;
} CBase;
struct VInterface;
typedef struct CInterface
{
    VT(struct VInterface)
} CBase;
struct VThis;
typedef struct CThis
{
    EXTENDS2(CBase,struct VThis)
    EXTENDS(CInterface)
} CThis;
但Coo可以不在类数据中嵌入虚函数表指针:
struct VBase; //虚函数类
typedef struct CBase
{
    int a;
} CBase;
struct VInterface;
typedef struct CInterface
{
} CBase;
struct VThis;
typedef struct CThis
{
    EXTENDS(CBase)
    EXTENDS(CInterface)
} CThis;
sizeof(CBase)是4,sizeof(CInterface)是0,sizeof(CThis)是4.使用时可能要将
虚函数表指针当参数转入需要函数.
下面再展示一种混合方式:
struct VBase; //虚函数类
typedef struct CBase
{
    VT(struct VBase) //虚函数表指针
    int a;
} CBase;
struct VInterface;
typedef struct CInterface
{ //无虚函数表指针
} CBase;
struct VThis;
typedef struct CThis
{
    EXTENDS(CInterface) //空的,占位
    EXTENDS2(CBase,struct VThis)
} CThis;
sizeof(CBase)是8,sizeof(CInterface)是0,sizeof(CThis)是8.主继承链嵌入
虚函数表指针,而接口等不嵌入虚函数表指针,有点像java
作者: OwnWaterloo    时间: 2010-06-04 16:07
回复 20# fera

这东西我已经下载过2次: 刚出现在cu, 以及回复在那个interface帖后。
结果是(我知道虽然文件很小, 但还是)没耐心看完就删了。
作者: pan_0326    时间: 2010-06-04 16:17
回复  fera

这东西我已经下载过2次: 刚出现在cu, 以及回复在那个interface帖后。
结果是(我知道虽然 ...
OwnWaterloo 发表于 2010-06-04 16:07



#define EXTENDS(s) \
    union \
    { \
        s s; \
        s; \
    };
这个宏是核心,借用java关键字extends,继承的意思,实际是嵌入数据.
VTable是建议规范,VT宏是嵌入虚函数表指针规范,其它宏是变体和辅助.
作者: OwnWaterloo    时间: 2010-06-04 17:15
回复 29# pan_0326

假设程序员A要解决P问题, A对解决这个问题的L库很熟悉。
L库可能就是A自己开发的, 也可能是别人开发的, 总之A很熟悉。

现在有人宣传解决P问题的另一个库N。
如果N没有什么特别明显的好处, 或者说N的宣传没有让A感到有很明显的好处, A会去深入研究并熟悉N, 然后使用N吗?


所以, 如果你想宣传这个东西, 建议把文档写得再详细一些。
比如你提到的第1个, 大小问题, 在我看来这是tradeoff —— 即优化一方面是建立在劣化另一方面的基础上 —— 并不是真正的优化。
所以其他的也就看不下去了, 不够吸引人。


1. C++不一定不具备这样的灵活性。

我不记得C++是否要求基类和子类成员之间在地址上有没有强制顺序。
有可能有强制, 并且有适当的理由。

也有可能没有这种强制, 只是编译器没有利用这个特性。
比如, C++不保证不同access section中的成员有相同的顺序。
理论上说, C++编译器就可以利用这个特性重新安排成员的顺序, 以优化存储。
注意, 这是真正的优化, 并不导致其他方面的劣化。
印象中, 至少gcc和msvc没有采用。

例子在: http://bbs.chinaunix.net/redirec ... 18&pid=12276162


一方面, 连真正可以优化的灵活性, 都不一定被C++编译器采用, 更别说会带来其他方面损失的灵活性。
另一方面, C++编译器不采用, 不能证明C++不具备这样的灵活性。
要证明, 需要查看C++标准确实在这方面有限制: 基类成员必须比子类成员有更低的地址。


2. 为什么这是tradeoff, 而不是optimization

因为子类到基类的转换需要做加法运算。
不以base作为起始, 可能会提高空间效率, 但损失时间效率是肯定的。
作者: pan_0326    时间: 2010-06-04 17:51
回复  pan_0326

假设程序员A要解决P问题, A对解决这个问题的L库很熟悉。
L库可能就是A自己开发的, 也 ...
OwnWaterloo 发表于 2010-06-04 17:15



看你对C++挺熟的,不应该看不懂coo.h,是不愿也,心理作用.
我也不知道C++有没有重排数据的规范,但现实使用的几个编译器都不会.求人不如求己,
等编译器器优化,还不如自己手摆.C和C++程序员研究到深处和java程序员是不同,不仅
要会用,还要知道怎么实现,做到最大控制.gcc编译器的优化总是不如意,靠等能急死,
编码时直接做些优化控制才踏实.
EXTENDS由于语法原因,天生具有手摆的自由.但这也不算什么,Coo本来就不想也不能和
C++比.
Coo在嵌入虚表指针这方面却是很灵活的,C++的多继承只有固定一个套路.
Coo最大的功劳是可以继承、多继承、虚函数、深层引用成员、深层引用基类,这对C来
说已经够了。
作者: OwnWaterloo    时间: 2010-06-04 20:20
本帖最后由 OwnWaterloo 于 2010-06-04 20:23 编辑

回复 33# pan_0326

1. 重排基类并不是优化, 而是损失时间效率换空间效率。
关于这个你怎么看?


2. 匿名union
这特性我眼馋很久了, 可惜C99也不支持它, 更别说C89了。
所以, 使用匿名union来实现继承并深层引用成员和基类是自相矛盾

C++才支持匿名union。
但C++从C+++98开始就支持继承(并能深层引用成员和基类), 而且C++编译器支持得还不错。

而C语言中的匿名union, 鬼知道什么编译器支持, 什么编译器不支持。
msvc支持吗? 支持。 但msvc本来就是C++编译器, 至少从VC6开始就是如此。
gcc支持吗?可以通过编译参数支持或者不支持。 但是,去搞个g++的后端就可以用C++了。
与其这样, 我还不如直接使用C++编译器。


所以, 这不是什么COO, 而是dialect C OO、gcc OO。
既然不具备C的可移植性和广泛性, 直接用C++得了。


同时, 用匿名union可以实现继承, 并能较为自然的引用祖先。
但是, 可以用匿名union实现多继承吗?

  1. struct A        { ... };
  2. struct B : A    { ... };
  3. struct C : A    { ... };
  4. struct D : B, C { ... };
复制代码
这也叫多继承。
D可以通过C::A和B::A引用两个不同的A。 匿名union没问题?


3. 关于OO
我对OO并不感冒, 所以对C、OO这种东西一向没兴趣, 因为我对OO没兴趣。

匿名union我也曾经打算用过, 用在类似linux/list.h的东西上。
一个2指针的节点, 既可以当作双链表节点, 也可以当作没有parent指针的二叉树节点, 甚至还可以当作单链表的节点。
我直接就将单指针的节点嵌入到双指针节点中去了, 并不需要什么EXTENDS

一个节点, 如果它有link1成员, 它就可以传递给单链表的函数。
如果它有link2成员, 它就可以传递给双链表和两节点二叉树的函数。
所以, 我不觉得一定需要将双指针节点理解为由单指针节点继承得到才能编程。
我打心眼里就把OO放在很低的优先级里。

非要将它理解为EXTENDS, 用OO去套这种关系, 只能说是学OO学傻了。

最终没有采用匿名union, 理由上面也说了, 是因为这不是任何一个C标准规定的东西


而COO、 去掉这个有可移植性问题, 有效率问题, 有多继承问题, 有问题的EXTENDS之后, 还剩什么?


我用到的C++ OO代码, 我都知道它们的C代码是如何表达的。
以我的经验, 这些C代码中存在的共性根本不是一个EXTENDS就可以表达的。
至少需要VA_ARG, 但我通常只在Clean C下编程, 所以C99的特性一般也是不用的。

本来想写一些代码来说明C++的部分OO代码如何翻译为C, 而这部分的C代码完全不需要EXTENDS。
写到一半放弃了。 感觉你也是个听不进劝的主, 写了也白写。
你继续弄COO好了。
作者: pan_0326    时间: 2010-06-04 23:43
回复  pan_0326

1. 重排基类并不是优化, 而是损失时间效率换空间效率。
关于这个你怎么看?


2.  ...
OwnWaterloo 发表于 2010-06-04 20:20



1.关于成员位置排列,这是深入C/C++必过的关,没有哪个编译器能自动做好.
2.匿名union,几乎所有C编译器都支持.匿名struct,gcc需要靠扩展选项.
  Coo确实使用了C标准的边缘特性,那是因为以前没有这么用的,将来不一定.
3.C++能完成的多继承Coo都能完成,因为你没试过,菱形多继承在Coo中没问题.
尽管是个很糟糕的例子
typedef struct A { ... } A;
typedef struct B { EXTENDS(A) } B;
typedef struct C { EXTENDS(A) } C;
typedef struct D { EXTENDS(B) EXTENDS(C) } D;
D d;
d.A //d.B.A
d.C.A //后出现的A不能跨层书写
4.C++翻译成C是可以的,但几乎无法阅读,用C来直接写更是痛苦.
用Coo可以方便许多,最起码可以用d.A代替麻烦的d.B.A,继承链越长越方便.
5.我并不鼓吹EXTENDS有什么神奇,优点只是插入点随意,跨层(深层)访问的书
写方便.
6.你那么歧视OO,还参与讨论什么interface,直接鄙视就得了.
作者: pan_0326    时间: 2010-06-05 10:55
本帖最后由 pan_0326 于 2010-06-05 12:36 编辑

详解EXTENDS
EXTENDS宏是Coo的核心,借用java的关键字extends,继承扩展的意思,
在Coo中当作"嵌入"更容易理解.它的原始朴素的形态是这样的:
#define EXTENDS(s) s s;
嵌入基类,并且用基类名作为成员名,这是为了记忆访问方便.
typedef struct CBase { int i; } CBase;
typedef struct T1 { EXTENDS(CBase) } T1;
T1 t; //t.CBase t.CBase.i
子类可以访问基类整体t.CBase,很满意;可t.CBase.i就不如C++的t.i
了,继承链越长越麻烦:
typedef struct T2 { EXTENDS(T1) } T2;
...
typedef struct TN { EXTENDS(TN_1) } TN;
TN t;
访问CBase要这么写:t.TN_1....T1.CBase
访问i要这么写:t.TN_1....T1.CBase.i
累死!怎么办?用匿名struct,它的特性就是可以直接访问内层:
#define EXTENDS(s) s;
访问i终于不用一长串了,直接t.i,很好!可无法访问CBase整体了,用强
制类型转换,是个坏主意.用匿名union结合上述两种方法得到最终的版本:
#define EXTENDS(s) \
    union \
    { \
        s s; \
        s; \
    };
这样任何深度的成员都有两种访问方式---跨层和逐层
t.TN_1....T1.CBase和t.TN_1....T1.CBase.i就是逐层,t.CBase和t.i就
是跨层,完美!
最后问题就是编译器支持情况,匿名union虽然不是C标准,但几乎所有的C编
译器都支持,因为它是C++标准.就像//注释先是C++标准,C在没出C99标准前
都纷纷支持一样.
匿名struct呢?C标准允许直接嵌入struct { ... };不许struct CBase;没
道理,gcc加上-fms-extensions选项就支持了.
还有成员重名问题,C标准没说,而许多编译器实现时都允许,这有什么坏处
呢?第一个可访问即可.
作者: 没本    时间: 2010-06-05 11:08
楼主把Coo配套的STL和Boost实现一份,我想还是会有人用的。
作者: pmerofc    时间: 2010-06-05 11:20
提示: 作者被禁止或删除 内容自动屏蔽
作者: pan_0326    时间: 2010-06-05 12:05
楼主把Coo配套的STL和Boost实现一份,我想还是会有人用的。
没本 发表于 2010-06-05 11:08



你把template和OO搞混了,用宏可以模拟些简单的template,
想用boost只能C++
作者: 没本    时间: 2010-06-05 12:21
你把template和OO搞混了,用宏可以模拟些简单的template,
想用boost只能C++
pan_0326 发表于 2010-06-05 12:05



    STL实现的主要是容器类,模板只是为了实现泛型容器类的途径之一,STL和Boost容器类并非全是依赖模板的。

本版有人发过C STL  http://libcstl.googlecode.com

ACL 也实现了一些C容器 http://acl.sourceforge.net/

GTK 当然更是有名的跨平台C库

你就一个OO实现,没有库的支持,谁用啊。
作者: pan_0326    时间: 2010-06-05 12:34
STL实现的主要是容器类,模板只是为了实现泛型容器类的途径之一,STL和Boost容器类并非全是依赖模 ...
没本 发表于 2010-06-05 12:21



Coo并不排斥其它C库
授人以鱼,不如授人以渔.
作者: xiaonanln    时间: 2010-06-06 14:20
不错
作者: pan_0326    时间: 2010-06-07 09:05
详解EXTENDS2
EXTENDS宏可以完成一般的继承功能,但有个小问题:
typedef struct CBase { VT(VBase) ... } CBase;
typedef struct CThis { EXTENDS(CBase) ... } CThis;
CThis t; //t.vt
VT宏是定义虚函数指针vt,t.vt的类型是const VBase*,而实际上
CThis扩展了虚函数表类VThis,希望t.vt的类型是const VThis*
才方便,用强制类型转换肯定行,但不安全.用数据覆盖!只听说函
数覆盖,数据也能覆盖吗?定义同名数据,排在前面的可访问,后面
的被覆盖:
#define EXTENDS2(s,v) \
    union \
    { \
        VT(v) \
        EXTENDS(s) \
    };
typedef struct CThis { EXTENDS2(CBase,VThis) ... } CThis;
这样一来,t.vt就是const VThis*,而t.CBase.vt是const VBase*,
它由于重名的原因,失去了跨层访问待遇.合并两个union得到最终
版本:
#define EXTENDS2(s,v) \
    union \
    { \
        VT(v) \
        s s; \
        s; \
    };
最后谈谈编译器支持,同名数据覆盖,C标准没说,很多编译器支持,
gcc和tcc都没问题.
但也带来一个问题:union的默认初始化.CThis t={...};
C标准没说,有些编译器不支持,如tcc,现已修改好了;gcc初始化第
一个,那么只能初始化vt,而其它数据将被忽略,这决不是我们所愿.
将初始化改为最后一个就可以躲开了,反正C标准没定义,怎么都合
理.现阶段gcc没改好,但可以用C99标准的指定初始化代替:
CThis t={.CBase={..};};
而一般用不着这种初始化,用构造函数CThis_CThis(&t);
作者: beetleleo    时间: 2010-06-07 21:54
像是gtk种出现过这样的写法!
作者: pan_0326    时间: 2010-06-08 08:50
像是gtk种出现过这样的写法!
beetleleo 发表于 2010-06-07 21:54



struct _GtkWidget
{
  /* The object structure needs to be the first
   *  element in the widget structure in order for
   *  the object mechanism to work correctly. This
   *  allows a GtkWidget pointer to be cast to a
   *  GtkObject pointer.
   */
  GtkObject object;
  ...
};
struct _GtkWidgetClass
{
  /* The object class structure needs to be the first
   *  element in the widget class structure in order for
   *  the class mechanism to work correctly. This allows a
   *  GtkWidgetClass pointer to be cast to a GtkObjectClass
   *  pointer.
   */
  GtkObjectClass parent_class;
  ...
};
以上是从gtk上截取了一段代码,可以看出确实使用了oo的思想,但却没有
Coo的便利,从注释来看可能还要用到强制类型转换.从书写到安全两方面
都不如Coo:
typedef struct _GtkWidget
{
    EXTENDS(GtkObject)
    ...
} _GtkWidget;
typedef struct _GtkWidgetClass
{
    EXTENDS(GtkObjectClass)
    ...
} _GtkWidgetClass;
作者: snow888    时间: 2010-06-08 15:58
这帖子没火???
作者: pan_0326    时间: 2010-06-09 06:09
本帖最后由 pan_0326 于 2010-06-09 07:15 编辑

虚继承
class CBase
{
public:
    int a;
};
class CT1 : public virtual CBase
{
public:
    int a1;
};
class CT2 : public virtual CBase
{
public:
    int a2;
};
class CThis : public CT1, public CT2
{
public:
    int i;
};
上面是C++中虚继承的例子,sizeof(CThis)是24,不是16,因为
CT1和CT2分别嵌入了CBase*来间接访问基类CBase,看看Coo实
现就明白了:
typedef struct CBase
{
    int a;
} CBase;
typedef struct _CT1
{
    CBase* pCBase; //虚继承
    int a1;
} _CT1;
typedef struct _CT2
{
    CBase* pCBase; //虚继承
    int a2;
} _CT2;
typedef struct CThis
{
    EXTENDS(_CT1)
    EXTENDS(_CT2)
    EXTENDS(CBase) //共享继承
    int i;
} CThis;
CThis嵌入了一份CBase共享于_CT1和_CT2,构造函数时装配pCBase.
_CT1和_CT2是不能直接单独使用的,包装后才行:
typedef struct CT1
{
    EXTENDS(_CT1)
    EXTENDS(CBase)
} CT1;
Coo还可以更灵活,允许其中一条路径是正常继承:
typedef struct CBase
{
    int a;
} CBase;
typedef struct CT1
{
    EXTENDS(CBase) //正常继承
    int a1;
} CT1;
typedef struct _CT2
{
    CBase* pCBase; //虚继承
    int a2;
} _CT2;
typedef struct CThis
{
    EXTENDS(CT1)
    EXTENDS(_CT2)
    int i;
} CThis;
由CT1提供CBase,共享于_CT2.现在sizeof(CThis)是20,少了一指针.
作者: bill15    时间: 2010-06-09 08:31
不必搞那些稀奇古怪的,C++挺好的,钻研它吧
等你成大师,可以推广你的咚咚的时候再拿出来说事
作者: pan_0326    时间: 2010-06-09 10:49
不必搞那些稀奇古怪的,C++挺好的,钻研它吧
等你成大师,可以推广你的咚咚的时候再拿出来说事
bill15 发表于 2010-06-09 08:31



其实我是一个程序员!
以后不带拿"大师"骂人的啊
作者: Cyberman.Wu    时间: 2010-06-09 16:32
我第一次听到这种说法,我不知道怎么用宏简单地实现同名函数
编译器用特殊的预处理程序将C++代码变成 ...
pan_0326 发表于 2010-06-04 11:45



建议你看一下C++作者的The Design and Evolution of C++。如你所想,C++最早没有真正的编译器,当时贝尔实验室的几个大拿是开发了一个CFront,实际上是把C++先“编译”成C语言,然后再用C编译器编译成可执行程序。好像泛型最早期是通过宏实现的,记不准确了。

其实语言本身的特性是为了实现OO,而不是OO本身吧;而且OO的设计方式也不是所有情况都适合。从目前看任何技术都有其局限性,虽然概念满天飞、新语言新特性层出不穷,但感觉程序设计史上真正有突破性的就是结构化设计吧。
作者: suavelee    时间: 2010-06-10 08:24
提示: 作者被禁止或删除 内容自动屏蔽
作者: gigabyte    时间: 2010-06-10 15:46
看起来不错
作者: 群雄逐鹿中原    时间: 2010-06-10 15:54
跟OIOIC相比,哪个更强一点?
作者: pan_0326    时间: 2010-06-11 09:41
Coo的析构和释放

struct CBase1;
typedef struct VBase1 //基类1虚表
{
    EXTENDS(VTable)
    void (*dtor)(struct CBase1*); //虚析构函数
} VBase1;
typedef struct CBase1 //基类1
{
    VT(VBase1);
} CBase1;

struct CBase2;
typedef struct VBase2 //基类2虚表
{
    EXTENDS(VTable)
    void (*dtor)(struct CBase2*);
} VBase2;
typedef struct CBase2 //基类2
{
    VT(VBase2);
} CBase2;

typedef struct VThis
{
    EXTENDS(VBase1)
    EXTENDS(VBase2)
} VThis;
typedef struct CThis
{
    EXTENDS2(CBase1,VThis)
    EXTENDS(CBase2)
    int* p;
} CThis;
void CThis_dtor(CThis* pThis) //析构函数
{
    if (pThis->p)
        free(pThis->p);
}
void CThis_CBase2_dtor(CBase2* pThis) //CBase2析构函数
{
    CThis_dtor(SUPER(CThis,CBase2,pThis));
}
const VThis _VThis=
{
    0,
    (void (*)(CBase1*))CThis_dtor,
    offsetof(CThis,CBase2),
    CThis_CBase2_dtor,
};
void CThis_CThis(CThis* pThis) //构造函数
{
    pThis->vt=&_VThis;
    pThis->p=(int*)malloc(sizeof(int));
}

int main()
{
    CThis* p=(CThis*)malloc(sizeof(CThis));
    CBase2* p2=&p->CBase2;
    CThis_CThis(p);
    p->vt->VBase2.dtor(p2); //p->dtor(&p->CBase1);
    FREE(p2,&p->vt->VBase2); //free(p);
    return 0;
}

上面用复杂的多继承为例子演示了析构与释放,并演示了几个宏的作用
offsetof:得到父类偏移
SUPER:从子类转换到父类指针
FREE: 通用释放
作者: zhujiang73    时间: 2010-06-11 10:21
回复 54# pan_0326


     多继承不常用,使用起来却比较复杂,我看你就别管多继承了, gtk 就是单继承一样很流行。 {:3_189:}
作者: pan_0326    时间: 2010-06-12 21:00
回复  pan_0326


     多继承不常用,使用起来却比较复杂,我看你就别管多继承了, gtk 就是单继承一样 ...
zhujiang73 发表于 2010-06-11 10:21



接口很常用(类似java),还是需要多继承实现的
typedef struct CBase { VT(VBase) ... } CBase;
typedef struct CInterfase {} CInterface; //empty
typedef struct CThis { EXTENDS(CInterface) EXTENDS2(CBase,VThis) ... } CThis;
作者: worldcupgogogo    时间: 2010-07-11 15:28
回复 1# pan_0326


    你做这个东西比OIOIC可差远了
作者: zhujiang73    时间: 2010-07-11 16:12
回复  pan_0326


    你做这个东西比OIOIC可差远了
worldcupgogogo 发表于 2010-07-11 15:28



     {:3_191:}  终于把大神招来了。  
作者: worldcupgogogo    时间: 2010-07-11 17:19
本帖最后由 worldcupgogogo 于 2010-07-11 17:22 编辑
终于把大神招来了。
zhujiang73 发表于 2010-07-11 16:12



    大神?你有什么高见?我感觉他这个东西真的不如OIOIC呀。你对他这个东西和OIOIC都很熟悉么?说说,俺也学习个
作者: peidright    时间: 2010-07-11 18:38
回复 3# pan_0326

用c++ 搞ooc ,太恐怖了。。
作者: worldcupgogogo    时间: 2010-07-11 20:18
回复  pan_0326

用c++ 搞ooc ,太恐怖了。。
peidright 发表于 2010-07-11 18:38



哈哈,你真是一语道破呀,费了很大劲原来是在学习C++,没意思,呵呵。

你知道OIOIC么?OIOIC是在我所知道的用C面向对象技术中最优秀最有创意的,我非常佩服OIOIC作者的天赋,大家知不知道WGI就是用OIOIC做的,朋友给我推荐WGI后我才知道OIOIC的。
作者: zhujiang73    时间: 2010-07-11 21:55
哈哈,你真是一语道破呀,费了很大劲原来是在学习C++,没意思,呵呵。

你知道OIOIC么?OIOIC是在 ...
worldcupgogogo 发表于 2010-07-11 20:18



    大神恒久远,故事永流传。  

    http://topic.csdn.net/u/20080530 ... 7-8ade54b01d0c.html
作者: worldcupgogogo    时间: 2010-07-11 22:28
本帖最后由 worldcupgogogo 于 2010-07-11 22:42 编辑

回复 62# zhujiang73


    大神?你认为LZ做的东西很好?
那个帖子我早看过了,很经典。
作者: RDTYTRE    时间: 2010-07-12 11:48
关注。。。。。。。。
作者: pan_0326    时间: 2010-07-13 10:01
Rules of Coo

1. define class
typedef struct CBase { int a; ... } CBase;
typedef struct CBase { VT(VBase) ... } CBase;
    //include pointer of vitual table, its name must be "vt", it must be the first member
typedef struct CInterface {} CInterface;
    //may be empty, sizeof equals 0, align equals 1
2. inherit
typedef struct CThis { EXTENDS(CBase) ... } CThis;
typedef struct CThis { EXTENDS2(CBase,VThis) ... } CThis;
    //covers old pointer of vitual table
typedef struct CThis { EXTENDS(CBase) EXTENDS(CInterface) ... } CThis;
    //multiple inherits
typedef struct CThis { EXTENDS(CInterface) EXTENDS2(CBase,VThis) ... } CThis;
    //if CInterface is empty, may put it on the top
3. define vitual table class
typedef struct VBase { int (*Get)(const CBase*); ... } VBase;
typedef struct VBase { EXTENDS(VTable) ... } VBase;
    //advice to inherit from VTable, can use macro FREE
4. vitual table class inherit
typedef struct VThis { EXTENDS(VBase) ... } VThis;
typedef struct VThis { EXTENDS(VBase) EXTENDS(VInterface) ... } VThis;
    //multiple inherits too
5. visit member and base class
typedef struct CBase { int a; ... } CBase;
    typedef struct CThis { EXTENDS(CBase) ... } CThis;
    CThis t;
    //t.CBase is better than *(CBase*)&t
    //t.a is better than t.CBase.a
6. define vitual function
typedef struct VBase { int (*Get)(const CBase*); ... } VBase;
    int CBase_Get(const CBase* pThis) { return pThis->a; }
    typedef struct VThis { EXTENDS(VBase) ... } VThis;
    int CThis_CBase_Get(const CBase* pThis) { const CThis* p=SUPER(CThis,CBase,pThis); ... }
    //covers vitual function
    //macro SUPER coverts current class pointer to super class pointer
7. define vitual table
VBase _VBase={ CBase_Get, };
VThis _VThis={ ... offsetof(CThis,CBase), CThis_CBase_Get, ... };
    //don't use type conversion as much as possible
    //macro offsetof servers for macro FREE
8. constructor
void CBase_CBase(CBase* pThis) { ... }
void CBase_CBase(CBase* pThis) { pThis->vt=&_VBase; ... }
    //install the pointer of vitual table
9. FREE
typedef struct CThis { EXTENDS(CBase) EXTENDS(CBase1) ... } CThis;
    CThis* pThis; ... CBase1* p=&pThis->CBase1;
    FREE(p,p->vt);
10. virtual inherit
typedef struct CBase { ... } CBase;
    typedef struct _CT1 { CBase* pCBase; ... } _CT1;
    typedef struct _CT2 { CBase* pCBase; ... } _CT2;
    typedef struct CThis { EXTENDS(_CT1) EXTENDS(_CT2) EXTENDS(CBase) ... } CThis;
作者: snriyt    时间: 2010-07-13 16:14
挣分
作者: forumGpoint    时间: 2010-07-13 17:11
回复 65# pan_0326


    你能不能别闹呀,你这是在学C++
作者: xie995    时间: 2010-07-13 23:11
OOC不是很好吗?
作者: wavingflag    时间: 2010-07-13 23:43
Coo?用C面向对象?




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2