如何使用C语言的面向对象
我们都知道,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语言的面向对象的更多相关文章
- [java学习笔记]java语言核心----面向对象之this关键字
一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别:在构造函数中调用其它构造函数 原理: 代表的是当前对象. this就是所在函数 ...
- 第二十五节:Java语言基础-面向对象基础
面向对象 面向过程的代表主要是C语言,面向对象是相对面向过程而言,Java是面向对象的编程语言,面向过程是通过函数体现,面向过程主要是功能行为. 而对于面向对象而言,将功能封装到对象,所以面向对象是基 ...
- 比较分析C++、Java、Python、R语言的面向对象特征,这些特征如何实现的?有什么相同点?
一门课的课后题答案,在这里备份一下: 面向对象程序设计语言 – 比较分析C++.Java.Python.R语言的面向对象特征,这些特征如何实现的?有什么相同点? C++ 语言的面向对象特征: 对象模 ...
- 用C语言实现面向对象的开发
C语言的对象化模型 面向对象的特征主要包括: .封装,隐藏内部实现 .继承,复用现有代码 .多态,改写对象行为 采用C语言实现的关键是如何运用C语言本身的特性来实现上述面向对象的特征. 1.1 封装 ...
- 基于C语言的面向对象编程
嵌入式软件开发中,虽然很多的开发工具已经支持C++的开发,但是因为有时考虑运行效率和编程习惯,还是有很多人喜欢用C来开发嵌入式软件.Miro Samek说:"我在开发现场发现,很多嵌入式软件 ...
- 已看1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架、多线程(并发编程)、I/O(NIO)、Socket、JDBC、XML、反射等。[泛型]\
1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架.多线程(并发编程).I/O(NIO).Socket.JDBC.XML.反射等.[泛型]\1* ...
- luajit利用ffi结合C语言实现面向对象的封装库
luajit中.利用ffi能够嵌入C.眼下luajit的最新版是2.0.4,在这之前的版本号我还不清楚这个扩展库详细怎么样,只是在2.04中,真的非常爽. 既然是嵌入C代码.那么要说让lua支持 ...
- go语言之面向对象
Go 语言结构体 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型. 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合. 结构体表示一项记录,比如保存图 ...
- C 语言实现面向对象编程
转载 https://blog.csdn.net/onlyshi/article/details/81672279 C 语言实现面向对象编程1.引言面向对象编程(OOP)并不是一种特定的语言或者工具, ...
随机推荐
- web自动化测试(java)---测试过程中遇到的错误合集
摸索测试,不管是安装.调测第一个用例都会遇到各种各样的问题,或是自己的问题或是程序本身设置问题 只有把所有问题记录下来,才对得起自己的经历 1.设置firefox的执行文件错误 Exception i ...
- 用Eclipse导入Maven工程
步骤一 : 选择 “Import”操作 有两个途径可以选择 “Import”操作; 1>“File”--> "Import..." 2> 在 "Pro ...
- .net core build docker image
1.创建.net core web项目 2.添加Dockerfile文件 # 基于microsoft/dotnet:2.1-aspnetcore-runtime构建Docker Image FROM ...
- 如何理解 Linux 中的 load averages
原文:https://mp.weixin.qq.com/s?src=11×tamp=1533697106&ver=1047&signature=poqrJFfcNAB ...
- Hadoop项目实战-用户行为分析之应用概述(一)
1.概述 本课程的视频教程地址:<Hadoop 回顾> 好的,下面就开始本篇教程的内容分享,本篇教程我为大家介绍我们要做一个什么样的Hadoop项目,并且对Hadoop项目的基本特点和其中 ...
- docker学习系列(四):数据持久化
需要搞清楚一个概念的是,docker的容器设计理念是可以即开即用,用完可以随意删除,而新建容器是根据镜像进行渲染,容器的修改是不会影响到镜像,但是有时候容器里面运行的产生的数据(如mysql)或者配置 ...
- leetcode — two-sum-ii-input-array-is-sorted
import java.util.ArrayList; import java.util.List; /** * Source : https://oj.leetcode.com/problems/m ...
- Linux下lz4解压缩命令小结
lz4是一个让"人见人爱.花见花开"的压缩算法,能够在多核上很好的扩展.lz4在压缩率上略微逊色, 但是在解压速度上有着惊人的优势 (大概是gzip的3倍(多次测试对比)).因为压 ...
- Jenkins持续集成学习-Windows环境进行.Net开发1
目录 Jenkins持续集成学习-Windows环境进行.Net开发 目录 前言 目标 使用Jenkins 安装 添加.net环境配置 部署 结语 参考文档 Jenkins持续集成学习-Windows ...
- 教你分分钟搞定Python之Flask框架
用最短的时间开发一个数据操作接口,Python是王道! 一.安装pip .首先检查linux有没有安装python-pip包,终端执行 pip -V [root@ network-scripts]# ...