精华内容
下载资源
问答
  • C面向对象编程

    2018-06-08 17:08:00
    C面向对象编程 C语言面向对象编程 1. 定义一个SuperObject结构体, 里面包含最少的元素, 但是确实每一个对象都含有的, 这样可以实现多态 2. 每一个对象都是基于类的, 我们知道类都是单例对象, 所以...

    C面向对象编程

    C语言面向对象编程

        1. 定义一个SuperObject结构体, 里面包含最少的元素, 但是确实每一个对象都含有的, 这样可以实现多态
        2. 每一个对象都是基于类的, 我们知道类都是单例对象, 所以我们创建结构体, TypeObject(类似于Java中的class), 接着每一个Object结构体中
    都包含着一个对应类型的TypeObject指针, 比如"Hello world"这一个字符串对象所对应的结构体中有一个StrTypeObject示例, 这个StrTypeObject
    是由我们定义的TypeObject结构体创建的, 当然万物皆为对象, 所以还有MegaTypeObject作为TypeObject结构体的实例
        3. 注意: 在所有的Object结构体中, 都要SuperObject中所定义的所有的数据(主要是refcount, type_ptr(指向对应的class对象, 这里就是一
    个单例的, 所以方法就是在这里的, static修饰的东西也都在这里, 多态的实现也是在这里, 因为多态主要是为要用方法服务的)), 内置的对象都是静态的
        4. 用户定义的类, 则是需要动态通过TypeObject这个结构体创建出来的, 用户所定义的方法也要在该TypeObject中保存起来, 用于以后的调用, 其实
    在Java中至于对象有关的属性, 在这里原来的SuperObject因为包含的元素太少了不能满足我们的需求, 我们需要在定义一个含有一个dict的BasicSuperO
    bject结构体, 通过一个dict, 以"属性名":属性名值的形式来实现对每一个对象的属性保存, 而方法则在TypeObject中的dict中, 也通过类似的方法存储
        5. 通过以上的几点我们知道, 在TypeObject中定义方法和属性, 对应于Java中的static修饰的函数和属性, 都是与class有关, 与instance无关的,
    而在BasicObject中定义的则是至于instance有关的
        
        6. 在TypeObject中需要内置一些方法, 让每一个对象都有对应的处理操作, 实现继承
                可以:
                    1. 数值处理的函数的结构体
                    2. 序列处理的函数的结构体
                    3. 映射处理的函数的结构体
                则系统每一种内置对象分别填充对应的结构体函数指针, 并也在dict中存储, 这样在调用时就可以统一的调用了
        7. 为了有个性
            #define BUXAPI(return_type)  return_type
            BUXAPI(SuperObject *) so_dome();
            这样就告诉用户这是我们自己的API, 你们可以调用
        8. 需要内置的对象:
                int, float, string, mapping(命名空间中非常重要), list, stack, type
        9. 目录结构:
                Include, Objects, Tools, Doc, Demo, Lib, Module
                
        10. 在面向对象中, 对象之间的操作符, 应该都转为函数的操作
        11. 在Map中比较中应该调用每一个对象的equal方法, 如果类型不同则为false, 相同则比较真正比较的值, 返回一个内置的None对象
        12. 遇到变量的重复定义, 使用extern关键字, 这个时候可以使用一个宏定义#define JCAPI_DATA(datatype) extern datatype 使得表达更加的直观 

    其他

    1. 在C语言中定义了一个全局变量, 如果要直接为该全局进行赋值, 那么必须要赋常量值:0, NULL, "string", 如果要赋变量的值, 需要在函数中赋值
    2. 虽然这里讲的是面向对象的编程但是我在这里写的是一些技巧的东西
    
        如果有多个函数都结构相同的参数列表, 并且特别的长, 我们可以使用struct封装参数列表, 这样函数的参数列表就会简明一些, 为了方便构造结构体, 我们可以通过一个宏或者函数来创建该结构体
        
    3. C语言中要想实现foreach, 可以说使用宏定义
        
        #define for_each(s) \
            List *tmp = s.lists;
            
        调用时
            for_each() {
                ...code...
            }   
            
    
    posted @ 2018-06-08 17:08 Andrew_Chan 阅读(...) 评论(...) 编辑 收藏
    展开全文
  • ANSI C 面向对象编程. epub.epub格式更适合移动端阅读
  • visual c面向对象编程

    2012-06-09 15:58:09
    visual c面向对象编程视频介绍,有助于学习C++。
  • objective-c 面向对象编程 ,主要讲objiectve-c 的面向对象方面。
  • Object C 面向对象编程

    2014-08-29 17:13:50
    object c 语言面向对象编程教程, 描述了object c语言是如何实现面向编程的
  • C#面向对象编程-多态 1C# 中的方法重写使用关键字 a) override b) overload c) static d) inherit 2 以下的C#代码试图用来定义一个接口 public interface IFile{ int A; int delFile) { A = 3; } void disFile; } ...
  • 浙江大学城市学院实验四_C_面向对象编程(2) 作者 日期 实验四 C#面向对象编程2 课程名称 C#程序设计实验 实验项目名称 实验四 C#面向对象编程2 学生姓名 专业 学号 实验地点 实验日期 年 月 日 实验目的 1. 巩固面向...
  • C面向对象编程基础

    2011-11-15 14:41:03
    C++是一种静态数据类型检查的、支持多重编程范式的通用程序设计语言。它支持过程化程序设计、数据抽象、面向对象程序设计、制作图标等等泛型程序设计等多种程序设计风格。
  • c面向对象编程例子

    千次阅读 2016-03-26 18:00:08
     Redy的开发语言是C,但在源码中,有很多地方都使用到了面向对象编程的方法,例如:在基本数据类型这一个模块,所有的数据类型都继承robject;在抽象语法树模块,所有的节点都继承astobjct。在linux内核中,也有很...
     Redy的开发语言是C,但在源码中,有很多地方都使用到了面向对象编程的方法,例如:在基本数据类型这一个模块,所有的数据类型都继承robject;在抽象语法树模块,所有的节点都继承astobjct。在linux内核中,也有很多是使用的面向对象方法,在虚拟文件系统,驱动模型中都可以看到。c语言是一种结构化编程语言,以模块工能和处理过程设计为主,实现数据与代码分隔化。面向对象方法论中,核心是类,类是用于创造对象的模板,其三要素为:封装,继承,多态。C语言本身对面向对象的支持很弱,但可以通过一些技巧来实现。下面通过一个具体的实例来说明实现这此技巧。

    实例介简:

           在几何中,所有的几何类型都继承父类“形状(shape)”,父类“形状”有两处属性s_type和s_name。其中s_type用于表示该形状所属的类型,s_name用于表于该形状态的名称。而且父类shape还有两个虚接口,一个为shape_area用于返回该形状的面积,一个为shape_perimeter用于返回该形状的周长。所子继承“形状”的子类都必须实现这两个接口。



    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
      
      
    struct shape;
    struct shape_ops
    {
        /*返回几何体的面积*/
        float (*so_area)(struct shape*); 
        /*返回几何体的周长*/
        int (*so_perimeter)(struct shape*);
    };
    struct shape
    {
        int* s_type;
        char* s_name;
        struct shape_ops* s_ops; /*虚接口,所有子类必须实现*/
    };
    
    float shape_area(struct shape* s)  /*求形状面积*/
    {
        return s->s_ops->so_area(s);  
    }
    int shape_perimeter(struct shape* s) /*求周长*/
    {
        return s->s_ops->so_perimeter(s);
    }
    
    
    
    /*三角形*/
    struct triangle
    {
        struct shape t_base;
        int t_side_a;
        int t_side_b;
        int t_side_c;
    };
    
    float triangle_area(struct shape* s)  /*三角形面积,用海伦公式*/
    {
        struct triangle* t=(struct triangle*)s;
        int a=t->t_side_a;
        int b=t->t_side_b;
        int c=t->t_side_c;
        //float p=(a+b+c)/2;
    	float p=(a+b+c);
        return  p;//sqrt((p*(p-a)*(p-b)*(p-c)));
    }
    int triangle_perimeter(struct shape* s)  /*三角形周长*/
    {
        struct triangle* t=(struct triangle*)s;
        int a=t->t_side_a;
        int b=t->t_side_b;
        int c=t->t_side_c;
        return a+b+c;
    }
    struct shape_ops triangle_ops=    /*对父类虚接口的实现*/
    {
        triangle_area,
        triangle_perimeter,
    };
    
    
    struct triangle* triangle_create(int a,int b,int c)  /*创建三角形*/
    {
        //struct triangle* ret=(struct triangle*)malloc(sizeof (*ret));
    	struct triangle* ret=(struct triangle*)malloc(sizeof(struct triangle));
        ret->t_base.s_name="triangle";
        ret->t_base.s_ops=&triangle_ops;
        ret->t_side_a=a;
        ret->t_side_b=b;
        ret->t_side_c=c;
        return ret;
    }
    
    
    
    
    
    
    
    
    
    //几何体“矩形(rectangle)”继承父类“形状”,同样也实现的父类的两个虚接口。有两个属性r_width和r_height,分别表示矩形的长和宽。
    /*矩形*/
    struct rectangle
    {
        struct shape r_base;
        int r_width;
        int r_height;
    };
    
    float rectangle_area(struct shape* s)  /*矩形面积*/
    {
        struct rectangle* r=(struct rectangle*)s;
        return r->r_width*r->r_height;
    }
    int rectangle_perimeter(struct shape* s)/*矩形周长*/
    {
        struct rectangle* r=(struct rectangle*)s;
        return (r->r_width+r->r_height)*2;
    }
    struct shape_ops rectangle_ops=      /*对父类虚接口的实现*/
    {
        rectangle_area,
        rectangle_perimeter,
    };
    
    struct rectangle* rectangle_create(int width, int height)  /*创建矩形*/
    {
        struct rectangle* ret=(struct rectangle*)malloc(sizeof(*ret));
        ret->r_base.s_name="rectangle";
        ret->r_base.s_ops=&rectangle_ops;
        ret->r_height=height;
        ret->r_width=width;
        return ret;
    }
    
    
    
    
    
    
    
    
    
    int main()
    {
        struct shape *s[4];
        s[0]=triangle_create(5,5,4);
        s[1]=triangle_create(3,4,5);
        s[2]=rectangle_create(10,12);
        s[3]=rectangle_create(5,8);
    
        int i=0;
        for(i=0;i<4;i++)
        {
            float area=shape_area(s[i]);    
            int perimeter=shape_perimeter(s[i]);
            char* name=s[i]->s_name;
    
            printf("name:%s ,area:%.2f ,perimeter:%d\n",name,area,perimeter);
        }
        return 0;
    }




    展开全文
  • ANSI-C面向对象编程翻译-序言

    千次阅读 2010-11-21 20:23:00
    译者序:我刚刚做出了一个艰难的决定,我决定翻译这本《ANSI-C面向对象编程》。这本书是一位刚刚离职的技术狂同事推荐给我的,细看了一点发现这是一本非常棒的书。但是苦于本人英语不佳,从网上又没有搜到中文译本,...

    版权所有,转载请注明出处。本文地址:http://blog.csdn.net/SerenityMoon/archive/2010/11/21/6025498.aspx

     

    译者序:

     

    我刚刚做出了一个艰难的决定,我决定翻译这本《ANSI-C面向对象编程》。这本书是一位刚刚离职的技术狂同事推荐给我的,细看了一点发现这是一本非常棒的书。但是苦于本人英语不佳,从网上又没有搜到中文译本,于是我决定翻译它,方便我自己的阅读,也提供给诸位爱好编程的技术狂人们。

    C语言虽然是一门结构化的语言,但是它是一个非常有技巧的语言,用C可以写出非常优美、非常具有艺术性的代码来。C++脱胎于C,虽然是一门面向对象的语言,但是我不得不说,它的确是一门非常糟糕的语言,它的标准复杂到目前没有任何一款编译器支持C++的所有特性,而且不同的编译器甚至是同一款编译器的不同版本,对C++代码的理解是不一样的。由于多继承的引入,虽然C++是面向对象的,但是你需要比C更加地了解底层才能在胜任多继承情况下C++代码的调试。

    这本书从另一个角度去理解C,去看C是如何实现面向对象的。技术之外,我也更想去思考一下我们与老外思想上合技术上的差距,以及造成这种差距的原因。

    本人能力有限,翻译中难免有错误的地方,有感兴趣的童鞋希望不吝指摘。今天先翻译了序言,以后会定期更新。由于工作的原因,我不可能投入太大的精力到本书的翻译,预计每一至两周翻译一章。英文原本的下载地址是http://www.planetpdf.com/codecuts/pdfs/ooc.pdf

    2010年11月21日于沈阳

     

    目录:

     

    -

    -内容

    -1 抽象数据类型

    -2 动态连接

    -3 编程悟性Programming Savvy

    -4 继承

    -5 编程悟性Programming Savvy

    -6 类的层次结构

    -7 ooc 预处理器

    -8 动态类型检测Dynamic Type Checking

    -9 静态构造Static Construction

    -10 委托

    -11 类方法

    -12 持久对象

    -13 异常

    -14 递进消息Forwarding Messages

    -A ANSI-C 编程暗示Programming Hints

    -B ooc 预处理器Preprocessor

    -C 手册

    -参考书目

     

     

    序:

     

        没有能解决掉所有问题的编程技术。

        没有能只产生正确结果的编程语言。

        没有每个项目都该从头写的程序员。

        面向对象编程已经出现了十多年,它目前仍是解决问题的灵丹妙药。本质上,除了接受了二十多年来的一些好的编程法则外并没有什么新的东西带给我们。C++是一门新的语言因为它是面向对象的,如果你不想使用或者不知道如何使用那么你不需要使用它,因为普通的C就可以实现面向对象。虽然子程序的思想和计算机一样久远并且好的程序员总是随身携带着他们的工具和库,但是只有面向对象才可以在不同项目间实现代码复用。

        这本书不准备推崇面向对象或者批评传统的方式。我们准备以ANSI-C来发掘如何实现面向对象,有哪些技术,为什么这些技术能帮我们解决更大的问题,如何利用它的一般性以及更早的捕获异常。虽然我们会接触很多术语,如类、继承、实例、连接、方法、对象、多态等等,但是我们将会剥去其魔幻的外表,使用我们熟悉的事物来表述他们。

        我非常有意思的发现了ANSI-C其实是一门完全的面向对象的语言。如果想要和我分享这份乐趣你需要非常熟悉它,至少也要对结构、指针、原型和函数指针。通过这本书,你将遇到一个新语言”——按照Orwell和韦氏词典对一门语言的解释,语言的设计目的就是缩减思维的广度——而我会尽力证明,它不仅仅汇合了所有的那些你想汇聚到一起的良好的编程原则。结果,你可以成为一个更熟练的ANSI-C程序员。

    前六章建立ANSI-C做面向对象编程的基础。我们从一个抽象数据类型的信息隐藏技术开始,然后加入基于动态连接的通用函数,再通过谨慎地扩充结构来继承代码。最后,我们将上述所有放进一个类树中,来使代码更容易地维护。

        编程需要规范。良好的编程更需要很多的规范、众多原则和标准以及确保正确无误的防范措施。程序员使用工具,而优秀的程序员则制作工具来一劳永逸地处理那些重复的工作。用ANSI-C的面向对象的编程需要相当大量的不变的代码——名称可能变化但结构不变。因此,在第7章里我们搭建一个小小的预处理器,用来创建所需要的模板。它很像是另一个方言式面向对象的语言。但是它不应该这样被看待,它剔除方言中枯燥无味的东西,让我们专注于用更好的技术解决问题的创新。OOC有非常好的可塑性:我们创造了它,了解它,能够改变它,而且它可以如我们所愿的写ANSI-C代码。

        余下章节继续深入讨论我们的技术。第8章加入动态类型检测来实现错误的早期捕获。第9章讲我们通过使用自动初始化来防止另一类软件缺陷。第10章引入委托代理,说明类和回调函数如何协作,比如去简化标准主程序的生成这样的常规任务。其他章节专注于用类方法来堵塞内存泄漏,用一致的方法来存储和加载结构数据,和通过嵌套异常处理系统的规范错误的恢复。

        在最后一章,我们突破ANSI-C的限制,做了一个时髦的鼠标操作的计算器——先是针对curses然后是针对X Window系统。这个例子极好地表明:即使是不得不应对外部库和类树的风格,通过对象和类我们已然可以非常精致地进行设计和实现。

        每一章都有总结,这些总结中我试图给随意浏览的读者一个梗概以及它对此后章节的重要性。大多数的章节都有练习题,不过他们并不是正式的阐明性文字,因为我坚定的相信读者应当自己实践。由于该技术是我们从无到有建立起来的,所以尽管有些例子应该能够从中获益,但是我避免建立和使用庞大的类库。如果你想要真正地理解面向对象的编程,首先掌握该技术并且在代码设计阶段考虑你的选择更为重要;而开发中依赖使用他人的库应当在这稍后一点。

        本书的一个重要部分是所附源码软盘——其上有一个DOS文件系统,包括一个用来按照章节顺序来创建源码的简单shell脚本。

    还有一个ReadMe文件——在你执行make命令前要先查阅这个文件。使用一个工具如diff并且追踪根类和ooc报告在后续章节的演化也是非常有帮助的。

        这里展现的技术源自我对C++的失望。当时我需要面向对象技术实现一个交互式编程语言,但我意识到无法用C++建立一个可移植的东西来。于是我转向我所了解的ANSI-C,并且我完全能够做到要做的事情。我将这个些告诉组里的几个人,然后他们用同样的方法完成了他们的工作。如果不是布赖恩·克尼翰(Brian Kernighan)以及我的出版商翰斯·尼科拉斯(Hans-Joachim Niclas)、约翰·维特(John Wait)鼓励我出版这些笔记(在适当的时候全新的展现一下),这个事情很可能就止于此,我的注解也就是一时的时尚了。我感谢他们和所有帮助并且经历本书不断完善的人。最后但是并非不重要的,感谢我的家庭——面向对象当然绝不可能代替餐桌上的面包。

     

     

    199310月于Hollage     阿塞尔-托彼亚斯·斯莱内尔(Axel-Tobias Schreiner

     

    展开全文
  • 用C语言进行面向对象编程,有一本非常古老的书,Object-Oriented Programming With ANSI-C。1994出版的,很多OOC的思想可能都是源于这本书。但我觉得,没人会把书里的模型用到实际项目里,因为过于复杂了。没有必要...

    用C语言进行面向对象编程,有一本非常古老的书,Object-Oriented Programming With ANSI-C。1994出版的,很多OOC的思想可能都是源于这本书。但我觉得,没人会把书里的模型用到实际项目里,因为过于复杂了。没有必要搞出一套OOP的语法,把C模拟的和C++一样,那还不如直接使用C++。

    Mojoc使用了一套极度轻量级的OOC编程模型,在实践中很好的完成了OOP的抽象。有以下几个特点:
    * 没有使用宏来扩展语法。
    * 没有函数虚表的概念。
    * 没有终极祖先Object。
    * 没有刻意隐藏数据。
    * 没有访问权限的控制。

    宏可以做一些有意思的事情,但是会增加复杂性。有个C的开源项目利用宏,把C宏成了函数式语言,完全创造了新的高层次抽象语法,有兴趣的可以看看,orangeduck/Cello。所以,我的原则是能不用宏就不用,尽量使用C原生的语法就很纯粹 (当然在使用过程中会感到一些限制)。

    面向对象是一种看待数据和行为的视角,其核心是简单而明确的。但OOP语言提供的语法糖和规则是复杂的,是为了最大限度的把错误消除在编译期,并减少编写抽象层的复杂度,也可以理解为不太信任程序员。而C的理念是相信程序员能做对事情。所以,我的初衷是用C去实现抽象视角,不提供抽象语法糖,而是保持C语法固有的简单。

    Mojoc的OOC规则,设计思考了很久,在使用过程中反复调整了很多次,一直在边用边修改,尝试了很多种写法,最终形成了现在这个极简的形式。在实现Spine骨骼动画Runtime的时候,是对照着官方Java版本移植的,这套规则很好的实现了Java的OOP,Mojoc Spine 与 Java Spine。下面就介绍一下Mojoc的OOC规则,源代码中充满了这种写法。

    单例

    Mojoc中单例是非常重要的抽象结构。在C语言中,数据(struct)和行为(function)是独立的,并且没有命名空间。我利用单例充当命名空间,去打包一组行为,也可以理解为把行为像数据一样封装起来。这样就形成了平行的数据封装和行为封装,而一个类就是一组固定的行为和一组可以复制的数据模板。

    抽象单例的形式有很多,这里使用了最简单的方式。

    // 在.h文件中定义
    struct ADrawable
    {
        Drawable* (*Create)();  
        void      (*Init)  (Drawable* outDrawable);
    };
    
    
    extern struct ADrawable ADrawable[1];
    
    
    // 在.c文件中实现
    static Drawable* Create()
    {
        return (Drawable*) malloc(sizeof(Drawable));
    }
    
    
    static void Init(Drawable* outDrawable)
    {
        // init outDrawable
    }
    
    
    struct ADrawable ADrawable[1] =
    {
        Create,  
        Init,
    };
    • ADrawable 就是全局单例对象。
    • 利用了struct类型名称和变量名称,所属不同的命名空间,都命名为ADrawable。
    • ADrawable[1]是为了把ADrawable定义为数组,这样ADrawable就是数组名,可以像指针一样使用。struct成员变量也大量使用了这样的形式。
    • ADrawable 绑定了一组局部行为的实现,初始化的时候就已经确定了。
    • 并没有限制struct ADrawable定义其它的对象,单例的形式依靠的是约定和对约定的理解。

    封装

    正如前面所说,利用struct对数据和行为来进行封装。

    typedef struct Drawable Drawable;  
    struct  Drawable  
    {  
        float positionX;  
        float positionY;  
    };
    
    
    typedef struct 
    {  
        Drawable* (*Create)();  
        void      (*Init)  (Drawable* outDrawable);  
    }  
    ADrawable;  
    
    
    extern ADrawable ADrawable[1]; 
    • Drawable 封装数据,非单例类型,都会使用typedef定义别名,去除定义时候的struct书写。
    • ADrawable 封装行为。因为有了命名空间,所以函数不需要加上全名前缀,来避免冲突。
    • Create 使用malloc在堆上复制Drawable模板数据,相当与new关键字。
    • Init 初始化已有的Drawable模板数据,通常会在栈上定义Drawable,让Init初始化然后使用,最后自动销毁不需要free。也可以,在继承的时候初始化父类数据模板。

    继承

    父类struct变量嵌入子类struct类型,成为子类的成员变量,就是继承。这个情况下,一次malloc会创建继承链上所有的内存空间,一次free也可以释放继承链上所有的内存空间。

    typedef struct Drawable Drawable;  
    struct  Drawable  
    {  
        int a;
    };
    
    
    typedef struct
    {
        Drawable drawable[1];
    }
    Sprite;
    
    
    struct ASprite
    {
        Sprite* (*Create)();  
        void    (*Init)  (Sprite* outSprite);  
    };
    • Drawable 是父类,Sprite 是子类。
    • drawable[1]可以作为指针使用,但内存空间全部属于Sprite。
    • ASprite 的Create和Init中,需要间接调用ADrawable的Init来初始化父类数据。
    • 这里继承并不需要把drawable放在第一个成员的位置,并且可以用这种形式,继承无限多个父类。
    子类访问父类,直接简单的使用成员运算符就好了。那么,如何从父类访问子类 ?
    /**
     * Get struct pointer from member pointer
     */
    #define AStruct_GetParent2(memberPtr, structType) \
        ((structType*) ((char*) memberPtr - offsetof(structType, memberPtr)))
    
    
    Sprite* sprite = AStruct_GetParent2(drawable, Sprite);
    • 这里使用了一个宏,来获取父类在子类结构中的,数据偏移。
    • 然后使用父类指针与数据偏移,就可以获得子类数据的地址了。
    • 这样父类也可以看成一个接口,子类去实现接口,利用父类接口可以调用子类不同的实现,从而体现了多态性。

    组合

    struct指针变量嵌入另一个struct类型,成为另一个struct的成员变量,就是组合。这时候组合的struct指针对应内存就需要单独管理,需要额外的malloc和free。组合的目的是为了共享数据和行为。

    typedef struct Drawable Drawable;  
    struct  Drawable  
    {  
        Drawable* parent;
    }; 
    • parent 被组合进了 Drawable,parent的内存有其自身的Create和Init管理。
    • 同样一个struct可以组合任意多个struct。

    多态

    typedef struct Drawable Drawable;  
    struct  Drawable  
    {   
        void (*Draw)(Drawable* drawable);  
    };  
    • 我们把行为Draw封装在了Drawable中,这意味着,不同的Drawable可以有相同或不同的Draw行为的实现。
    typedef struct  
    {  
        Drawable drawable[1];  
    }  
    Hero;
    
    
    typedef struct  
    {  
        Drawable drawable[1];  
    }  
    Enemy; 
    
    
    Drawable drawables[] =   
    {  
        hero->drawable,  
        enemy->drawable,  
    };  
    
    
    for (int i = 0; i < 2; i++)  
    {  
        Drawable* drawable = drawables[i];  
        drawable->Draw(drawable);  
    • Hero和Enemy都继承了Drawable,并分别实现了Draw行为。
    • 而统一使用父类Drawable,在循环中调用Draw,会得到不同的行为调用。

    重写父类行为

    在继承链中,有时候需要重写父类的行为,有时候还需要调用父类的行为。

    typedef struct  
    {  
        Drawable drawable[1];  
    }  
    Sprite;  
    
    
    struct ASprite
    {  
        void (*Draw)(Drawable* drawable);  
    };  
    
    
    extern ASprite ASprite;  
    • 需要被重写的行为,就需要被提取到单例中来。比如这里Sprite所实现的Draw行为,被放到了ASprite中。
    • 这样,Sprite的Draw被覆盖了,其本身的Draw还储存在ASprite中供子类使用。
    typedef struct  
    {  
        Sprite sprite[1];  
    }  
    SpriteBatch;
    
    
    // subclass implementation  
    static void SpriteBatchDraw(Drawable* drawable)  
    {  
          // call father  
          ASprite->Draw(drawable);
    
          // do extra things...
    }  
    
    
    // override
    spriteBatch->sprite->drawable->Draw = SpriteBatchDraw;
    • SpriteBatch 又继承了 Sprite,并且覆盖了Draw方法。
    • 而在SpriteBatch的Draw实现中,首先调用了父类Sprite的Draw方法。

    内存管理

    就如前面所说,继承没有什么问题,但是组合就需要处理共享的内存空间。这里有两种情况。

    • 第一,组合的struct没有共享,这样只需要在外层struct提供一个Release方法,用来释放其组合struct的内存空间即可。所以,凡是有组合的struct,都需要提供Release方法,删除的时候先调用Release,然后在free。

    • 第二,组合的struct被多个其它struct共享,这时候就不知道在什么时候对组合的struct进行清理。一般会想到用计数器,或是独立的内存管理机制。但我觉得有些复杂,并没有去实现,但也没有更好的方法。目前,我的做法是,把共享的组合struct指针放到一个容器里,等到某一个确定的检查点统一处理,比如关卡切换。

    总结

    数据和行为,并没有本质的却别。行为其实也是一种数据,可以被传递,封装,替换。在C中行为的代理就是函数指针,其本身也就是一个地址数据。

    组合与继承,其本质是数据结构的构造,因为C的语法还是把数据与行为分开的,所以继承多个父类数据,并不会把父类固定的行为一起打包,就不会感觉到违和感,也没有什么限制。

    Mojoc的OOC规则就是简单的实现面向对象的抽象,没有模拟任何一个OOP语言的语法形式。原生的语法最大限度的降低了学习成本和心智负担,但需要配合详细的注释才能表达清楚设计意图,并且使用的时候有一些繁琐,没有简便的语法糖可用。

    实例

    Drawable.h
    Drawable.c
    Sprite.h
    Sprite.c
    Struct.h


    「OOC是一种视角」

    展开全文
  • Object-C面向对象编程

    2016-08-27 21:21:37
    遵守非正式协议通过继承带特定类别的NSObject来实现,而遵守正式协议则有专门的Object-C语法. 遵守非正式协议不要求实现协议中定义所有方法,而遵守正式协议则必须实现协议中定义的所有方法. @optional:...
  • 1. 面向对象编程 用解决现实中的问题的办法来解决计算机问题。 1.1 对象 Anything is Object. 万物皆对象。 现实中对象是一种客观的存在,程序中对象是一片内存空间。 对象之间各司其职,各尽所能,对象功能...
  • 在(一)中已经说过,Objective C的语言特性继承了C的特点,这些... 还是直接上手objective C面向对象特性。  在创建类之前用@interface标记传递给编译器信息:下面将定义一个类了  先看一个类的声明实例:  @in
  • 面向对象编程思想核心就是 万物皆对象 , 我们能见的每一个实物都是对象 。 要我讲解的话,很简单。 比方说, 我们把“人”看作是一个类即人类,有一个人叫“小宝”。那么这里说的“小宝”就是一个对象。 ...
  • 刚刚使用Objective-C 写了一个面向对象的程序,现在将一些知识点归结如下: 1)Objective-C的类定义包含两个部分,一是类接口的声明,二是类方法的实现。 2)所有的 Objective-C的所有编译指示都以@打头。 a)类...
  •  今天主要讲得是面向对象编程的原理,至于思想老师说得用漫长时间才能去领悟. 说正题 首先写第一个OC程序 #import int main(int argc, const char * argv[]) { @autoreleasepool { NSLog(@"hel
  • 我中意的C面向对象编程模式

    千次阅读 2011-08-18 20:35:56
     Java和C++的类,继承,构造函数,析构函数,虚函数,多态,Factory Method工厂方法这些面向对象的特性,C也可以很好的实现,下面结合在项目过程中的个人爱好,来说明用C实现面向对象编码  例子采用person基类...
  • main.cpp #include #include #include typedef void (*PrintFunc)(void *arg); int main() { PrintFunc print_cc; PrintFunc print_cpp;... print_cc = (PrintFunc)&CClass_print; print_cpp = (Pri
  • 1、构造与析构 让我们先实现一个简单的字符串数据类型,在后面的章节里,我们会把它放入一个集合中。 在创建一个新的字符串时,我们分配一块动态的缓冲区来保存它所包含的文本...new() 负责创建一个对象,而delete()
  • 1.1数据类型数据类型是每种编程语言不可缺少的一部分。ANSI-C 有 int,double 和 char 这几种。程序员们很少满足于现状,而编程语言通常会提供了从预定义的类型创建新数据类型的机制。一种简单的方法是构造集合如数...
  • C 语言实现面向对象编程

    万次阅读 多人点赞 2018-08-14 18:36:38
    C 语言实现面向对象编程 1、引言 面向对象编程(OOP)并不是一种特定的语言或者工具,它只是一种设计方法、设计思想。它表现出来的三个最基本的特性就是封装、继承与多态。很多面向对象的编程语言已经包含这三...
  • c语言面向对象编程中的类 C ++中的面向对象编程 (Object Oriented Programming in C++) Object Oriented programming is a programming style that is associated with the concept of Class, Objects and various ...
  • 程序性编程: 程序性编程可以定义为基于...可以将面向对象编程定义为基于对象概念的编程模型。对象包含属性形式的数据和方法形式的代码。在面向对象编程中,计算机程序是使用与现实世界交互的对象的概念来设计..
  • 为数不多的面向过程编程的语言。 之前写python,虽然理解了类是个什么,但是不太清楚到底怎么用。 我之前的理解: 类:相当于C语言里的结构体,可以自己定义各种别的value,而且还可以在类里写函数。 那么这个函数和...
  • C面向对象编程-000-面向对象-2020-3-16 目录一、面向对象概述(1)封装(2)继承(3)多态二、面向对象与面向过程编程1.面向过程编程(1)软件重用性差(2)软件可维护性差(3)开发出的软件不能满足用户需要2.面向对象编程3...
  • 标准C面向对象编程能力扩展 for study c/c++
  • 面向对象编程(OOP)

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,865
精华内容 4,746
关键字:

c面向对象编程