Linux内核之C语言实现面向对象机制

本文详细介绍了如何在C语言中实现面向对象编程,包括封装、继承和多态的基本概念及其实现方法。通过实例展示了如何使用结构体和函数指针在C语言中模拟类和对象的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

  我们都知道C语言是一门面向过程的编程语言,但你如果认为C语言只能用来编写面向过程式的程序,那只能说你对C语言,或者说对Linux不是非常了解。
  As we all konw,Linux操作系统大部分都是用C语言写的,而在编写linux中,大佬们优美的应用C语言写出了OO(面向对象)的操作系统。
  关于Linux内核中利用的OO思想的具体体现,网上有很多好的文章,我在这就不班门弄斧了,感兴趣的可以看看一下几篇文章

  c风格的面向对象–linux内核学习
  linux对象系统—kobject, ktype, kset, subsys
  linux设备模型与内核中的面向对象思想

本篇博客的目的是实践一下,是利用C语言来简单实现OO的程序。

C语言简单实现面向对象

面向对象主要包括三部分,封装、继承、多态。下面的代码也会按照这个顺序来实现。

 

封装

  所谓封装,在C++、JAVA或者其他的面向对象语言中有天生的支持,使用class就可以创造一个类,在类中把属性和方法集成在一起。在C语言中,也有一个对应的关键字,那就是struct(结构体),这也是C语言中天生的,不过这个天生的结构体本质上只能封装变量(对应C++中的属性),如果想利用struct封装方法的话,必须利用函数指针(本质上是个变量)这个东东,用这个指针指向具体的函数地址(函数名),来达到间接封装方法的目的。
如下所示:

#include <stdio.h>

struct parent_node
{
    int par_val;		//结构体中的属性

    void (*set_par_val)(int ,struct parent_node *);		//结构体中的方法
    int (*get_par_val)(struct parent_node *);       //此处需要指向本结构体的指针参数,为了外部的函数找到本自身,相当于C++中的this指针


};

//在外部实现具体的函数
int get_val(struct parent_node *par_node)
{
    return par_node->par_val;
}
void set_val(int val,struct parent_node *par_node)
{
    par_node->par_val = val;
}


int main()
{
    int tmp;
    //测试C语言中的封装
    struct parent_node par_node;		//相当于C++中的对象
   
    par_node.get_par_val = get_val;		//把函数地址赋给对象中的函数指针变量,此语句之后,对象的方法才真正绑定
    par_node.set_par_val = set_val;

    par_node.set_par_val(10,&par_node);
    tmp = par_node.get_par_val(&par_node);

    printf("parent_node's val = %d\n",tmp);

    return 0;
}

  C语言中就是利用这种方式来实现OO的封装,不过我们必须知道,C语言的封装并没有C++那样的private、protecte和public的访问控制,所以,这是C语言的一个缺点(简单,封装的不够彻底),也是C语言的一个优点(灵活性更高),这一点在整个面向对象和面向过程中都有体现。

 
 
 

继承

  广义上说,C++中实现代码、类等的复用主要有两种方式,一个是继承,即通过子类继承父类来达到使用父类已有的资源。另一个就是组合,也就是一个类通过包含另一个类的实体(比如A中包含B类的一个对象),用这种方式实现代码复用。
  对于C语言,前者是不谈了(C语言本身没有继承的概念),代码的复用主要是通过类似上面说的组合来间接实现的。

如下所示:

#include <stdio.h>

//父类结点
struct parent_node
{
    int par_val;											//结构体中的方法

    void (*set_par_val)(int ,struct parent_node *);			//结构体中的方法
    int (*get_par_val)(struct parent_node *);       //此处需要指向本结构体的指针参数,为了外部的函数找到本自身,相当于C++中的this指针
    

};

//子类结点
struct son_node
{
    struct parent_node par_node;			//包含父节点

    int son_val;							//子类特有的属性
    int (*get_son_val)(struct son_node * );			//子类特有的方法


};

//在外部实现具体的函数
int get_val(struct parent_node *par_node)
{
    return par_node->par_val;
}

void set_val(int val,struct parent_node *par_node)
{
    par_node->par_val = val;
}


int get_son_val(struct son_node * _son_node)
{
    return _son_node->son_val;
}


int main()
{
    int tmp;

    //测试C语言中的继承
    struct son_node _son_node;

    _son_node.par_node.get_par_val = get_val;		//初始化父类的成员
    _son_node.par_node.set_par_val = set_val;	
    _son_node.son_val = 20;							//初始化子类特有的成员
    _son_node.get_son_val = get_son_val;

    _son_node.par_node.set_par_val(15,&_son_node.par_node);			//调用父类的方法
    tmp = _son_node.par_node.get_par_val(&_son_node.par_node);
    printf("parent's val in son_node = %d\n",tmp);

    tmp = _son_node.get_son_val(&_son_node);
    printf("son_node 's val = %d\n",tmp);


    return 0;
}

  同样,我们可以看到,狭义上说,C语言中的继承并不是面向对象中说的那种继承的概念,但是其可以实现和继承一样的作用(代码重用)。

 
 
 

多态

  所谓多态,具体点指的是父类指针调用同一个函数,最终的结果会根据子类不同的实现而产生不同的结果。抽象的说,派生类可以向基类对象那样使用,同样的消息既可以发送给基类对象也可以给派生类对象。

  C语言中实现多态的机制之一是利用在子类中填充父类的通用函数指针,将它们指向具体的函数来实现的。

示例如下:

#include <stdio.h>

//父类结点
struct parent_node
{
    int par_val;

    void (*set_par_val)(int ,struct parent_node *);
    int (*get_par_val)(struct parent_node *);       //此处需要指向本结构体的指针参数,为了外部的函数找到本自身,相当于C++中的this指针

    void (*mul_sta)();				//用于实现多态的父类函数通用指针
};

//子类结点
struct son_node
{
    struct parent_node par_node;

    int son_val;
    int (*get_son_val)(struct son_node * );


};

int get_val(struct parent_node *par_node)
{
    return par_node->par_val;
}

void set_val(int val,struct parent_node *par_node)
{
    par_node->par_val = val;
}


int get_son_val(struct son_node * _son_node)
{
    return _son_node->son_val;
}

//多态
void mul_sta_son2()
{
    printf("this is polymorphism for son2\n");
}

//多态
void mul_sta_son1()
{
    printf("this is polymorphism for son1\n");
}

int main()
{
    int tmp;

    //测试C语言中的多态
    struct son_node son1,son2,*son;		//定义两个子类结点
    son1.par_node.mul_sta = mul_sta_son1;		//填充不同的函数实现
    son2.par_node.mul_sta = mul_sta_son2;

    son = &son1;                //指向son1
    son->par_node.mul_sta();		

    son = &son2;                //指向son2
    son->par_node.mul_sta();		//和上面语句一样,但是最终调用的方法不同


    return 0;
}

确切的说,上面的模拟不能算作正儿八经的多态,顶多有点C++静态多态的点点影子。

后言

 
  C语言中面向对象的实现总体上来说是“婉转”的方式,它并不是天生就支持的,也正是因为这样,它比天生就支持面向对象的语言要简单不少,也快的多。(我们系主任说过,C比C++快10倍,C++比java快10倍)。
   这里还要说两点我对语言的看法:
   第一,面向对象是一种思想,可以应用到不同的语言中。本人觉得学习C++最重要的是学习这种思想,而不仅仅是C++上的一些特性。
   第二,孔夫子告诉我们,每种语言出现必然有它的道理,一定会有它的优点。C++虽然比C语言慢,但并能说以后就不用C++了。C++慢有它慢的道理(相对来说,C++的复用性、代码出错率等要比C语言高,C++把它慢的时间大部分都花在这上面了)。我觉得,语言只是实现现实问题的工具,并不需要太拘泥于哪种哪种语言,重要的是看你要解决什么问题。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值