C语言模拟实现继承、多态

来源:互联网 发布:驾照查分软件 编辑:程序博客网 时间:2024/06/06 02:09

一、面向对象与面向过程

说到C语言和C++的区别有人就会说C语言是面向过程的语言,而C++是面向对象的语言。那么到什么是面向过程?什么又是面向对象呢?下面我就简单的说说我对与面向过程和面向对象的认识。
1)什么是面向对象和面向过程?
面向过程就是分析解决问题的步骤,然后用函数把这些步骤一步一步的进行实现,在使用的时候进行一一调用就行了,注重的是对于过程的分析。面向对象则是把构成问题的事进行分成各个对象,建立对象的目的也不仅仅是完成这一个个步骤,而是描述各个问题在解决的过程中所发生的行为。
2)面向对象和面向过程的区别?
面向过程的设计方法采用函数来描述数据的操作,但将函数与操作的数据进行分离开来。
面向对象的设计方法是将对象和数据进行封装起来成为一个整体。
面向过程以设计步骤为过程,后期难以维护。
面向对象设计以数据为中心,数据相对与功能来说具有较强的稳定性更加易于维护。
3)面向对象的三大特征
封装:
对于封装来说就是数据与具体操作实现的代码都放在某个对象的内部,使这些代码的具体细节不被外界发现,只留下一些接口供外部来使用,而不能一任何的形式来对象内部的实现。使用封装能够隐藏具体的实现的细节,使代码更加易于维护并且保证了系统的安全性。
继承:
继承机制是面向对象程序设计使代码进行复用的最重要的手段,他允许程序员在保证类原有类特性的基础上进行扩展来增加功能。这样新产生的类就被称为派生类,继承就可以表现面向对象机制的的层次结构。
多态:
多态简单点说就是“一个接口,多种实现”,就是同一种事物表现出的多种形态。多态在面向对象语言中是指:接口多种的不同实现方式。也就是复用相同接口,实现不同操作。C++多态支持两种多态性,编译时多态和运行时多态。编译时多态是通过重载函数来实现的,运行时多态是通过虚函数来实现的。静态多态:编译器在编译期间完成,编译器根据函数实参的类型(可能会隐式类型转换),可推断出要调用哪个函数,如果有对应的函数就调用相应的函数,否则就报一个编译错误。动态多态:在函数执行期间(非编译期)判断所引用对象的实际类型,根据实际类型的调用相应的方法。使用virtual关键字修饰类的成员函数,指明该函数为虚函数,派生类需要重新实现,编译器将实现动态绑定。
总的来说:封装可以隐藏实现细节包括包含私有成员,使得代码模块增加安全指数;继承可以扩展已存在的模块,为了增加代码的复用性;多态则是为了保证类在继承和派生的时候,类的实例被正确调用,实现了接口的重用。

二、实现继承、多态

如果要说到让C语言来模拟实现C++的继承和多态,那么我们得知道什么是C++ 的继承和多态。
下面用简单代码来讲一下什么是C++的继承和多态:

#pragma once#include <iostream>using namespace std;struct A{    virtual void fun()    //通过虚函数实现    {        cout<<"A:fun()"<<endl;    }    int a;};struct B:public A     {    virtual void fun()    //通过虚函数实现(子类的关键字virtual可加可不加)    {        cout<<"B:fun()"<<endl;    }    int b;};void test(){    A a;    //父类对象a    B b;    //子类对象b    A* p1 = &a;   //父类指针指向父类的对象    p1->fun();    //调用父类的同名函数    p1 = &b;      //让父类指针指向子类的对象    p1->fun();    //调用子类的同名函数}int main(){    test();    return 0;}

这里写图片描述
C语言来模拟实现:

#pragma once#include <iostream>using namespace std;typedef void (*FUN)();      //定义一个函数指针来实现对成员函数的继承struct _A       //父类{    FUN _fun;   //C语言中结构体不能包含函数只能用函数指针在外面实现    int _a;};struct _B         //子类{    _A _a_;     //在子类中定义一个基类的对象即可实现对父类的继承    int _b;};void _fA()       //父类的同名函数{    printf("_A:_fun()\n");}void _fB()       //子类的同名函数{    printf("_B:_fun()\n");}void Test(){    _A _a;        _B _b;        _a._fun = _fA;        //父类的对象调用父类的同名函数    _b._a_._fun = _fB;    //子类的对象调用子类的同名函数    _A* p2 = &_a;   //定义一个父类指针指向父类的对象    p2->_fun();     //调用父类的同名函数    p2 = (_A*)&_b;  //让父类指针指向子类的对象,由于类型不匹配所以要进行强转    p2->_fun();     //调用子类的同名函数}int main(){    Test();    return 0;}

这里写图片描述

0 0