我们都知道,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. shell编程中的循环语句

    while循环直接从文件中读取 while read line do command done < filename until循环 until 条件 do command done for循环 ...

  2. 使用JDBC连接各种数据库

    项目需要连多钟数据库,把链接的关键部分在这里记录下来. 1.Oracle8/8i/9i数据库(thin模式) Class.forName("oracle.jdbc.driver.Oracle ...

  3. mysql 开发进阶篇系列 35 工具篇 mysqldump(数据导出工具)

    一.概述 mysqldump客户端工具是用来备份数据库或在不同数据库之间进行数据迁移.备份内容包含创建表或装载表的sql语句.mysqldump目前是mysql中最常用的备份工具. 三种方式来调用my ...

  4. Linux下网络文件系统NFS服务搭建易错点总结

    一.环境准备: 1 [root@czh ~]# cat /etc/redhat-release 2 CentOS release 6.7 (Final) 3 [root@czh ~]# uname - ...

  5. php 获取中文字符串首字母

    <?php $limit=array( //gb2312 拼音排序 array(45217,45252), //A array(45253,45760), //B array(45761,463 ...

  6. macOS 系统 .DS_Store 文件详解

    .DS_Store 文件 .DS_Store 是 Finder 用来存储这个文件夹的显示属性的:比如文件图标的摆放位置. 显示/隐藏 Mac 隐藏文件 显示:defaults write com.ap ...

  7. windows上使用tensorboard

    因为我的环境变量设置的不是python3.5,所以走了一些弯路. 启动tensorboard后,graphs里总是什么都没有 最后再stackoverflow里找到答案 https://stackov ...

  8. How do I close a single buffer (out of many) in Vim?

    I open several files in Vim by, for example, running vim a/*.php which opens 23 files. I then make m ...

  9. JNI和NDK基础

    引言 JNI是Java Native Interface(Java本地接口),是为了方便Java调用C和C++等本地代码所封装的一层接口. NDK是Android提供的一个工具集合,通过NDK可以在A ...

  10. Vue 爬坑之路(十二)—— vue-cli 3.x 搭建项目

    Vue Cli 3 官方文档:https://cli.vuejs.org/zh/guide/ 一.安装 @vue/cli 更新到 3.x 之后,vue-cli 的包名从 vue-cli 改成了 @vu ...