我们都知道,C++才是面向对象的语言,但是C语言是否能使用面向对象的功能?

(1)继承性

 typedef struct _parent
{
int data_parent;
}Parent;
typedef struct _Child
{
struct _parent parent;
int data_child;
}Child;

在设计C语言继承性的时候,我们需要做的就是把基础数据放在继承的结构的首位置即可。这样,不管是数据的访问、数据的强转、数据的访问都不会有什么问题。

(2)封装性

class的类成员默认情况下都是private,而struct的成员都是public(不能改变),所以如何让C语言实现封装的功能呢?答案就是函数指针;这在内核中得到了广泛的应用;

 struct _Data;
typedef void (*process)(struct _Data* pData);
typedef struct _Data
{
int value;
process pProcess;
}Data;

封装性的意义在于,函数和数据是绑在一起的,数据和数据是绑在一起的。这样,我们就可以通过简单的一个结构指针访问到所有的数据,遍历所有的函数。封装性,这是类拥有的属性,当然也是数据结构体拥有的属性。

(3)多态性

在C++中,多态通常都是使用虚函数来实现的,但是C语言中并没有虚函数,如何实现重载呢?

答案也显而易见,也是函数指针的扩展,以下面例子为例:

 #include <stdio.h>
#include <stdlib.h> //虚函数表结构
struct base_vtbl
{
void(*dance)(void *);
void(*jump)(void *);
}; //基类
struct base
{
/*virtual table*/
struct base_vtbl *vptr;
}; void base_dance(void *this)
{
printf("base dance\n");
} void base_jump(void *this)
{
printf("base jump\n");
} /* global vtable for base */
struct base_vtbl base_table =
{
base_dance,
base_jump
}; //基类的构造函数
struct base * new_base()
{
struct base *temp = (struct base *)malloc(sizeof(struct base));
temp->vptr = &base_table;
return temp;
} //派生类
struct derived1
{
struct base super;
/*derived members */
int high;
}; void derived1_dance(void * this)
{
/*implementation of derived1's dance function */
printf("derived1 dance\n");
} void derived1_jump(void * this)
{
/*implementation of derived1's jump function */
struct derived1* temp = (struct derived1 *)this;
printf("derived1 jump:%d\n", temp->high);
} /*global vtable for derived1 */
struct base_vtbl derived1_table =
{
(void(*)(void *))&derived1_dance,
(void(*)(void *))&derived1_jump
}; //派生类的构造函数
struct derived1 * new_derived1(int h)
{
struct derived1 * temp= (struct derived1 *)malloc(sizeof(struct derived1));
temp->super.vptr = &derived1_table;
temp->high = h;
return temp;
} int main(void)
{ struct base * bas = new_base();
//这里调用的是基类的成员函数
bas->vptr->dance((void *)bas);
bas->vptr->jump((void *)bas); struct derived1 * child = new_derived1();
//基类指针指向派生类
bas = (struct base *)child; //这里调用的其实是派生类的成员函数
bas->vptr->dance((void *)bas);
bas->vptr->jump((void *)bas);
return ;
}

综上所述,可以实现C语言的面向对象功能;

如何使用C语言的面向对象的更多相关文章

  1. [java学习笔记]java语言核心----面向对象之this关键字

    一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别:在构造函数中调用其它构造函数 原理:         代表的是当前对象.         this就是所在函数 ...

  2. 第二十五节:Java语言基础-面向对象基础

    面向对象 面向过程的代表主要是C语言,面向对象是相对面向过程而言,Java是面向对象的编程语言,面向过程是通过函数体现,面向过程主要是功能行为. 而对于面向对象而言,将功能封装到对象,所以面向对象是基 ...

  3. 比较分析C++、Java、Python、R语言的面向对象特征,这些特征如何实现的?有什么相同点?

    一门课的课后题答案,在这里备份一下: 面向对象程序设计语言 –  比较分析C++.Java.Python.R语言的面向对象特征,这些特征如何实现的?有什么相同点? C++ 语言的面向对象特征: 对象模 ...

  4. 用C语言实现面向对象的开发

    C语言的对象化模型 面向对象的特征主要包括: .封装,隐藏内部实现 .继承,复用现有代码 .多态,改写对象行为 采用C语言实现的关键是如何运用C语言本身的特性来实现上述面向对象的特征. 1.1 封装 ...

  5. 基于C语言的面向对象编程

    嵌入式软件开发中,虽然很多的开发工具已经支持C++的开发,但是因为有时考虑运行效率和编程习惯,还是有很多人喜欢用C来开发嵌入式软件.Miro Samek说:"我在开发现场发现,很多嵌入式软件 ...

  6. 已看1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架、多线程(并发编程)、I/O(NIO)、Socket、JDBC、XML、反射等。[泛型]\

    1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架.多线程(并发编程).I/O(NIO).Socket.JDBC.XML.反射等.[泛型]\1* ...

  7. luajit利用ffi结合C语言实现面向对象的封装库

    luajit中.利用ffi能够嵌入C.眼下luajit的最新版是2.0.4,在这之前的版本号我还不清楚这个扩展库详细怎么样,只是在2.04中,真的非常爽.  既然是嵌入C代码.那么要说让lua支持 ...

  8. go语言之面向对象

    Go 语言结构体 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型. 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合. 结构体表示一项记录,比如保存图 ...

  9. C 语言实现面向对象编程

    转载 https://blog.csdn.net/onlyshi/article/details/81672279 C 语言实现面向对象编程1.引言面向对象编程(OOP)并不是一种特定的语言或者工具, ...

随机推荐

  1. 把本地项目放进新建的仓库(idea)

    1,获取仓库地址 比如: git@bitbucket.org:360717118/springboot_servlet-filter-listener-file.git,   2,idea 设置:

  2. 211. Orchard学习 二 2、ManualResetEvent 与 AutoResetEvent

    一.Orchard里异步请求处理线程队列的控制 Orchard的Orchard.WarmupStarter模块,为HttpApplication.BeginRequest时间附加了一个异步处理事件:B ...

  3. 利用jquery操作隐藏table某一列

    本文版权归 远方的风lyh和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. //隐藏表格第一列 $('tr').find('th:eq(0)').hide(); $('tr').f ...

  4. 以ActiveMQ为例JAVA消息中间件学习【4】——消息中间件实际应用场景

    前言 当前真正学习消息中间件,当前已经走到了,可以简单的使用,网上有很多那种复杂的高可用的架构,但是那些都是对于一些比较大型的项目来说的. 对于一些小型的项目可能用不到那么大的架构,于是我们需要从最简 ...

  5. LearnOpenGL学习笔记(二)——着色器简单理解

    着色器在OpenGL中发挥着重要作用,它就像一个画笔,将输入的数据流,转为数学坐标,再将三维坐标变成二维坐标(针对我们现在用的二维显示器,全息显示器肯是三维的),再把二维坐标实际的像素点位置(这里面肯 ...

  6. SOA&微服务&服务网格&高可用

    SOA 架构 SOA 全称是:Service Oriented Architecture,“面向服务的架构”. 它是一种设计理念,其中包含多个服务,服务之间通过相互依赖最终提供一系列完整的功能. 各个 ...

  7. 内核开发知识第一讲.内核中的数据类型.重要数据结构.常用内核API函数.

    一丶内核中的数据类型 在内核中.程序的编写不能简单的用基本数据类型了. 因为操作系统不同.很有可能造成数据类型的长度不一.而产生重大问题.所以在内核中. 数据类型都一定重定义了. 数据类型 重定义数据 ...

  8. Tirgger SimpleTrigger CronTrigger(四)

    触发器通用属性: jobKey:表示job实例的标识,触发器被触发时,指定的job实例会被执行. startTime:表示触发器的时间表 首次被触发的时间,他的值类型为java.uti.Date. e ...

  9. vuejs深入浅出—基础篇

    一.从HelloWorld说起 任何语言的都是从Hello World开始的,VueJs也不例外,直接上代码: <script src="https://unpkg.com/vue/d ...

  10. IP白名单添加了当前IP,获取access_token时依然报出错误码40164的坑

    开发公众号网页时,想要调用微信API接口,令人无奈的是,想要调用各接口都需使用access_token,于是,获取access_token的征途开始了…… 1.开发者基本配置 (1) 公众平台官网登录 ...