lianzhong008 发表于 2015-7-24 10:31:20

C语言面向对象基础特征行为实例

        RT_Thread是类Unix风格的代码风格,里面大量应用了C语言的对象化模型技术,我的基础目的是学习这个操作系统的,后面被它的面向对象编程的思想
所吸引住,与其说是在研究操作系统不如说是在感受前辈门的抽象编程的思想。今天和大家分享RT_Thread的对象化模型技术的基本原理。它实质是运用了c语
言的面向对象的特征思想。
        C语言面向对象的三大特征:
        1、封装,隐藏内部实现
        2、继承,复用现有代码
        3、多态,改写对象行为
RT_Thread里面林林总总的封装思想,详细的拆分都可以寻觅到这三个影子。

        下面普及基础知识

      封装是一种信息隐蔽技术,它体现于类的说明,是对象的重要特性。封装使数据和加工该数据的方法(函数)封装为一个整体,以实现独立性很强的模块,使得用户只能见到对象的外特性(对象能接受哪些消息,具有那些处理能力),而对象的内特性(保存内部状态的私有数据和实现加工能力的算法)对用户是隐蔽的。封装的目的在于把对象的设计者和对象者的使用分开,使用者不必知晓行为实现的细节,只须用设计者提供的消息来访问该对象。

        继承性是子类自动共享父类之间数据和方法的机制。它由类的派生功能体现。一个类直接继承其它类的全部描述,同时可修改和扩充。继承具有传递性。继承分为单继承(一个子类只有一父类)和多重继承(一个类有多个父类,当前RT-Thread的对象系统不能支持)。类的对象是各自封闭的,如果没继承性机制,则类对象中数据、方法就会出现大量重复。继承不仅支持系统的可重用性,而且还促进系统的可扩充性。具体代码片段如下:
       
#include <stdio.h>
#include <stdlib.h>
//父类
struct parent_class
{
        int a,b;
        char *c;
};
//子类
struct child_class
{
        struct parent_class p;
        int a,b;
};
//demo test
void test_demo(void)
{
        struct child_class child,*child_ptr;
        struct parent_class *parent_ptr;
        child_ptr = &child;
        parent_ptr = (struct parent_class *)&child;
       
       parent_ptr->a = 1;
         parent_ptr->b = 2;
      parent_ptr->c = "lable";
      child_ptr->a = 100;
      child_ptr->b = 200;
        printf("parent_ptr->a = %d\r\nparent_ptr->b = %d\r\nparent_ptr->c = %s\r\n\r\n",parent_ptr->a,parent_ptr->b,parent_ptr->c);
        printf("child_ptr->a = %d\r\nchild_ptr->b = %d\r\n",child_ptr->a,child_ptr->b);
}
int main()
{
        printf("Inherit test\n");
        test_demo();
        return 0;
}
执行结果:
Inherit test
parent_ptr->a = 1
parent_ptr->b = 2
parent_ptr->c = lable

child_ptr->a = 100
child_ptr->b = 200

        多态,对象根据所接收的消息而做出动作。同一消息为不同的对象接受时可产生完全不同的行动,这种现象称为多态性。利用多态性用户可发送一个通用的信息,而将所有的实现细节都留给接受消息的对象自行决定,如是,同一消息即可调用不同的方法。例如:RT-Thread系统中的设备:抽象设备具备接口统一的读写接口。串口是设备的一种,也应支持设备的读写。但串口的读写操作是串口所特有的,不应和其他设备操作完全相同,例如操作串口的操作不应应用于SD卡设备中。多态性的实现受到继承性的支持,利用类继承的层次关系,把具有通用功能的协议存放在类层次中尽可能高的地方,而将实现这一功能的不同方法置于较低层次,这样,在这些低层次上生成的对象就能给通用消息以不同的响应。RT-Thread对象模型采用结构封装中使用函数指针的形式达到面向对象中多态的效果。具体代码片段如下:
#include <stdio.h>
#include <stdlib.h>
//抽象父类
struct parent_class
{
        int a;
        void (*vfunc)(struct parent_class *,int a);
};
//抽象父类的方法
void parent_class_vfunc(struct parent_class *parent_self_ptr,int a)
{
        //调用对象自己本身的虚拟函数
        printf("parent_class_vfunc\n");
        parent_self_ptr->vfunc(parent_self_ptr,a);
}
//子类继承parent_class
struct child_class1
{
        struct parent_class parent;
        int b;
};
//子类虚拟函数实现
void child1_class_vfunc(struct child_class1 *child1_self_ptr,int a)
{
        printf("child1_class_vfunc\n");
        child1_self_ptr->b = a + 10;
}
//子类构造函数
void child1_class_init(struct child_class1 *child1_self_ptr)
{
        struct parent_class *parent;
        //获取子类的父类指针
        parent = (struct parent_class *)child1_self_ptr;
        //设置子类的虚函数
        parent->vfunc = child1_class_vfunc;
}
//子类继承parent_class
struct child_class2
{
        struct parent_class parent;
        int b;
};
//子类虚拟函数实现
void child2_class_vfunc(struct child_class2 *child2_self_ptr,int a)
{
       
        printf("child2_class_vfunc\n");
        child2_self_ptr->b = a + 10;
}
//子类构造函数
void child2_class_init(struct child_class2 *child2_self_ptr)
{
        struct parent_class *parent;
        //获取子类的父类指针
        parent = (struct parent_class *)child2_self_ptr;
        //设置子类的虚函数
        parent->vfunc = child2_class_vfunc;
}
int main()
{
        struct child_class1 child1,*child1_ptr;
        struct child_class2 child2,*child2_ptr;
        struct parent_class *parent_ptr;
        //child1初始化
        child1_ptr = &child1;
        parent_ptr = (struct parent_class *)child1_ptr;
        child1_ptr->b = 10;
        child1_class_init(child1_ptr);
        parent_ptr->vfunc((struct parent_class *)child1_ptr,20);

        //child2初始化
       child2_ptr = &child2;
       parent_ptr = (struct parent_class *)child2_ptr;
       child2_ptr->b = 20;
       child2_class_init(child2_ptr);
       parent_ptr->vfunc((struct parent_class *)child2_ptr, 20);
       return 0;
}
执行结果:
child1_class_vfunc
child2_class_vfunc
                                                                                                                                          
                                                                                       




ibichao 发表于 2015-7-24 10:56:23

C实现C++的面向对象,很麻烦,简单点封装一下代码还好,复杂点多态、继承,还不如直接用C++,用C实现太鸡肋了。

Okar 发表于 2015-7-24 10:57:39

指针果然是C语言的精华啊

cdh 发表于 2015-7-24 10:58:00

顶LZ,收藏了继续看。

ysyt_3 发表于 2015-7-24 11:14:59

楼主厉害,隐藏很深

kevin_me 发表于 2015-7-24 11:27:43

C语言复杂的搞不定,简单的逻辑指针还能搞搞。

这就是硬件专业的差距。要学习啊

so_so_so_so 发表于 2015-7-24 11:29:40

学习。。。

sandman 发表于 2015-7-24 11:38:40

c语言编程可借荐go语言的设计和风格

bbglx 发表于 2015-7-24 11:41:36

学习下C++的思想

onepower 发表于 2015-7-24 11:44:54

晕菜, 还C语言的对象化模型技术,直接用C++就是了;

takashiki 发表于 2015-7-24 12:05:28

LZ,我是非常的不明白,为什么用C模拟C++就非得把函数也封装到结构体内而且还和封装的数据平级排列。

比如:人作为一个对象,可能拥有姓名、性别、年龄等属性,可以具有吃饭、睡觉等等动作,在C++中可以封装成人.吃饭();但是吃饭这个动作并不是人固有的属性,你为什么用C把他和姓名、性别等等属性一样封装到一起呢????我是从来没有见过所谓的封装就是一股脑儿啥都往里塞,就称之为封装的。
再有,你自己比较一下C和C++封装的所谓“对象”,用sizeof测试一下,差别大么?不能说同一个人,用C++描述,他就苗条了;用C描述,他就发福了对不对。

“刻鹄不成尚类鹜,画虎不成反类犬”不知是不是这类隔三差五蹦出来高呼“面向对象”的真实写照。

bondxie3 发表于 2015-7-24 12:14:52

收藏!仔细学习! 楼主来个系列教程啊!

ibichao 发表于 2015-7-24 12:23:32

我来说一下,真想搞面向对象,还是得老老实实学C++;
不要用C去模拟,光用C去模拟,是体现不了C++的精髓的。

love_zjb 发表于 2015-7-24 12:48:19

感觉楼主分析的不错,很到位。

lianzhong008 发表于 2015-7-24 12:56:04

takashiki 发表于 2015-7-24 12:05
LZ,我是非常的不明白,为什么用C模拟C++就非得把函数也封装到结构体内而且还和封装的数据平级排列。

比如 ...

        C语言是面向过程的编程语言,C++是面向对象的编程语言,C语言由于自身的局限并不能全完实现C++的所有特性,
如你提到的可能涉及的C++类内有public、private、protect的访问权限,单纯的C并不具备这样的功能。我从事的是嵌入式
软件开发,在我这个行业的业界内基本上都是用C语言开发驱动程序的。第一类似性质的开发编译器缺乏对C++的支持,第
二C++的特性会损耗系统内存资源和运行速度。
        所以我们只能用C去实现面向对象的残缺美,至少目前是这个业界是这样。来实现我们代码的复用和优化我们的架构。
仅以此学习与分享。

wiser803 发表于 2015-7-24 13:05:55

说实在的,RT核的核心在于实时性和效率,用C来描述已经绰绰有余。而C++类的封装继承等模型是用来在大型或实时性要求不高的桌面程序设计时可以发挥很好效果,但将这两者捏在一起未必能够大小通吃,最后结局可想而知。

dswkl11 发表于 2015-7-24 13:57:21

实用就好

cdh 发表于 2015-7-24 14:01:12

只求神似,不求完全一致,够用就好。顶LZ.。

lianzhong008 发表于 2015-7-24 14:20:07

ibichao 发表于 2015-7-24 12:23
我来说一下,真想搞面向对象,还是得老老实实学C++;
不要用C去模拟,光用C去模拟,是体现不了C++的精髓的 ...

        C++博大精深,各种设计思想更是可以利用C++发挥的淋漓尽致,我修学过C++,也曾经系统的自学过C++,自学的初衷也是
希望优化自己的C代码及架构,哈哈,帮助其实是真不小,目前在研究新起的OOC。

zhdiamond 发表于 2015-7-24 15:35:54

lianzhong008 发表于 2015-7-24 12:56
C语言是面向过程的编程语言,C++是面向对象的编程语言,C语言由于自身的局限并不能全完实现C++的所有特 ...

说得好!

ibichao 发表于 2015-7-24 16:26:41

lianzhong008 发表于 2015-7-24 14:20
C++博大精深,各种设计思想更是可以利用C++发挥的淋漓尽致,我修学过C++,也曾经系统的自学过C++,自学 ...

C中没有this指针,虚函数表,当你熟悉C++后,你会发现你的想法是多么不现实,
给你举个例子:

在C++的成员函数中操作成员变量,如下

class A{
public:
        void fun(){
                m_nValue = 0;               
        }
private:
        int m_nValue;
};

void main()
{
        A a;
        a.fun();
}

在C中即使封装的再好也得如下操作。

struct A{
        int value;
        void(*pFun)(struct a *this);
};

void fun(struct a *this)
{
        this->value = 0;
}

void main()
{
        struct A a = {0,fun};
        a.pFun(&a);
}
到此你已看出C模拟C++的面向对象是多么烦索,简单的还能搞搞.复杂一点的,还是 forgot it !

sbk100 发表于 2015-7-24 23:51:10

学习一下 不喜欢c++

lianzhong008 发表于 2015-7-25 06:27:56

wiser803 发表于 2015-7-24 13:05
说实在的,RT核的核心在于实时性和效率,用C来描述已经绰绰有余。而C++类的封装继承等模型是用来在大型或实 ...

        嗯嗯,C语言的可移植性及其高效的目标程序的执行效率使其在编写操作系统方面具有一定的优势。

Ray______ 发表于 2015-7-25 08:16:40

这贴对于我还是挺有帮助的,通过c理解了以前理解不了的oo思想

wind2100 发表于 2015-7-25 08:54:51

这不就是C 结构体吗? 没看出来 和C++ 对像有太大关系。结构体本来就接近于类的概念。

bbglx 发表于 2015-7-26 18:07:24

takashiki 发表于 2015-7-24 12:05
LZ,我是非常的不明白,为什么用C模拟C++就非得把函数也封装到结构体内而且还和封装的数据平级排列。

比如 ...

可不可以这样认为,函数指针也是个数据,相当于标志位,用于选择不同的执行函数。
而且不这样的话怎么给外面一个统一的接口。

tianheyun12 发表于 2015-7-28 14:18:21

区别在于,用C实现封装和多态都需要自己重构。C++直接拿来用就是。但是目前大部分单片机用C语言开发,学习这种封装很有必要。RTT基本上都是这种思想。这种方法将来不一定是最好的方法,但是现在没有比他更好的办法,用它来统一接口很有必要。

abcdzhy 发表于 2015-7-29 07:56:53

我觉得编程不能重复劳动,第一次编了,第二次可以很方便的拿来使用这样才最好,封装起来就可以达到这个效果,再说我们开发嵌入式就是用的C,谈什么C++也没有意义,我是支持楼主的。

qtds67 发表于 2015-7-29 10:38:20

学习学习,各有千秋

zenith1032 发表于 2015-7-31 16:20:05

很好的贴。

litrtleway 发表于 2015-9-18 13:34:54

好贴,C语言面向对象,Mark!

litrtleway 发表于 2015-9-18 13:45:33

好贴,C语言面向对象,Mark!

Yvan 发表于 2016-3-5 20:26:20

果断收藏!我也对嵌入式面向对象编程很感兴趣!

308594151 发表于 2016-3-5 22:24:55

mark一下

笑笑我笑了 发表于 2016-3-5 22:35:13

C++应该去研究更高端的东西啊,什么模板啊,boost啊之类的啊。
还是用C来做这些简单的事情比较好。

磊磊映画 发表于 2016-3-5 22:45:01

正是因为广大软件工程师发现,大量工作都是重复性运动,所以才出的标准库啊,大家要用直接调用,只不过在C 阶段体现的还不充分,到C++ 和 JAVA 开发的时候就非常明显了,库是一个发展方向

zmh169 发表于 2016-3-12 15:43:47

ST的新版电机库SDK都是用C-OOP写的,我感觉也挺好理解的。

jiang739707231 发表于 2016-5-27 08:19:14

狂顶,,,,果断收藏

myhonour 发表于 2016-5-27 08:50:26

收藏了继续看。

wt3333 发表于 2016-5-27 10:18:51

收藏了 认真学习下

wq_601840968 发表于 2016-5-27 10:48:44

zmh169 发表于 2016-3-12 15:43
ST的新版电机库SDK都是用C-OOP写的,我感觉也挺好理解的。

st的电机库主要用来控制什么电机的,都包含哪些算法呀

zmh169 发表于 2016-5-27 11:10:47

wq_601840968 发表于 2016-5-27 10:48
st的电机库主要用来控制什么电机的,都包含哪些算法呀

新版是针对永磁同步,2.0版可以控制三相异步电机和永磁同步,磁场定向控制算法。论坛里有,你下载安装看看就知道了。

wq_601840968 发表于 2016-5-27 11:22:46

zmh169 发表于 2016-5-27 11:10
新版是针对永磁同步,2.0版可以控制三相异步电机和永磁同步,磁场定向控制算法。论坛里有,你下载安装看 ...

好的 谢谢 ,对这块不太了解

greenflyqqq 发表于 2016-5-27 11:32:48

学习了,感觉C语言很强大啊

Yvan 发表于 2016-6-8 10:43:31

有错误:
parent_ptr->vfunc((struct parent_class *)child1_ptr,20);应该写成:
parent_ptr->vfunc(child1_ptr,20);吧?

ckhf 发表于 2016-6-12 16:11:26

顶起,不错的思想

lhj200304 发表于 2017-8-6 23:44:30

支持楼主,其他几位不要用c++来跟c比,没有可比性的。
页: [1]
查看完整版本: C语言面向对象基础特征行为实例