我们都知道,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. C# 本进程执行完毕后再执行下一线程

    最近做了一套MES集成系统,由上料到成品使自动化运行,其中生产过程是逐步的,但是每一个动作都需要独立的线程进行数据监听,那么就需要实现线程等待. 代码: using System; using Sys ...

  2. Xamarin.Android 使用ListView绑定数据

    使用ListView进行数据绑定 第一步:新建一个类,用于存储显示字段. namespace ListViewDataBIndDemo { public class Person { public i ...

  3. Linux_CentOS-服务器搭建 <二>

    Tomat安装: 说明: 源码安装,下载地址:http://tomcat.apache.org/.我下了个apache-tomcat-7.0.42.tar.gz 安装开始: 配置环境. JDK: vi ...

  4. 各种实现js继承的方法总结

    昨天主要介绍了原型,在js中,原型,原型链和继承是三个很重要的概念,而这几个概念也是面试中经常会被问到的问题,今天,就把昨天还没总结的原型链和继承继续做一个整理,希望大家一起学习,一起进步呀O(∩_∩ ...

  5. Shell 函数定义与调用

    linux shell 可以用户定义函数,然后在 shell 脚本中可以随便调用. 以一个计算两数之和的函数为例: #! /bin/bash # 函数定义 sum(){ return $(($1+$2 ...

  6. .14-浅析webpack源码之Watchpack模块

    解决掉了最头疼的DirectoryWatcher内部实现,这一节可以结束NodeWatchFileSystem模块. 关于watch的应用场景,仔细思考了下,这不就是热重载的核心嘛. 首先是监视文件, ...

  7. T-SQL:基础练习(杂)

    1.返回 每月最后一天订单 SELECT orderid, orderdate, custid, empid FROM Sales.Orders WHERE orderdate = EOMONTH(o ...

  8. Spark的优势

    首先了解一下Mapreduce 它最本质的两个过程就是Map和Reduce,Map的应用在于我们需要数据一对一的元素的映射转换,比如说进行截取,进行过滤,或者任何的转换操作,这些一对一的元素转换就称作 ...

  9. 单机安装Hadoop

    单机安装hadoop ------------------------------------------------------------------ 操作系统:centos7 64 位 hado ...

  10. 【Spring】7、拦截器HandlerInterceptor

    处理器拦截器简介 Spring Web MVC的处理器拦截器(如无特殊说明,下文所说的拦截器即处理器拦截器) 类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理.   常见 ...