C语言实现C++面向对象多态特性

C++语言基本语法中包含了面向对象的三大特性:封装,继承,多态。正是因为C++在语法层面上支持了这些面向对象特性,才使得大型项目会考虑用此语言来搭建平台或产品框架。其实也可以这样说,面向对象是相对于面向过程而言的,更多地是一种思维方式,世间万物皆对象,感觉跟毕达哥拉斯学派宣称那样:万物皆数。所以面向对象作为一种软件设计方式(当然面向对象还有独特的SOLID设计原则),其他语言完全可以借用,比如说C语言就可以。我们在linux内核代码中就可以经常看到面向对象的特性。比如文件操作中将属性与方法(一般定义为函数指针)封装到特定结构体中。我们知道,C++与C一样,是一门静态语言,当代码编译后,其函数地址就相对固定了,那是怎么通过运行时来改变函数行为的呢? C++教科书中有介绍说,多态是通过虚函数实现的。如果在基类某些函数前面声明为virtual,则C++编译器会在内存对象模型前面插入一个虚函数指针,该指针指向一个虚函数表,正是因为我们可以改变虚函数指针所指函数表地址,从而实现其多态操作。下面我们以一个简单的示例来用C实现C++的继承与多态特性。

/*
 *
 *C语言实现C++面向对象多态特性
 *  Created on: 2015年12月26日
 *      Author: @CodingGeek
 */
#include <stdio.h>
#include <stdlib.h>

struct base;

struct base_vtbl
{
    void(*dance)(struct base *);
    void(*jump)(struct base*, int high);
};

struct base
{
    struct base_vtbl *vptr;
    /*base members */
};

void base_dance(struct base *pb)
{
    pb->vptr->dance(pb);
}

void base_jump(struct base *pb, int high)
{
    pb->vptr->jump(pb, high);
}

void based_dance(struct base *pb)
{
    printf("base dance\n");
}

void based_jump(struct base *pb, int high)
{
    printf("base jump:%d\n", high);
}
/* global vtable for base */
struct base_vtbl base_table =
{
        based_dance,
        based_jump
};

void base_init(struct base *pb)
{
    pb->vptr = &base_table;
}

struct derived1
{
    struct base super;
    /*derived members */
};

void derived1_dance(struct derived1 *pd)
{
    /*implementation of derived1's dance function */
    printf("derived1 dance\n");
}

void derived1_jump(struct derived1 *pd, int high)
{
    /*implementation of derived1's jump function */
    printf("derived1 jump:%d\n", high);
}

/*global vtable for derived1 */
struct base_vtbl derived1_table =
{
    (void(*)(struct base *))&derived1_dance,
    (void(*)(struct base*, int))&derived1_jump
};

void derived1_init(struct derived1 *pd)
{
    pd->super.vptr = &derived1_table;
    /*init base members d->super.foo */
    /*init derived1 members d->foo */
}

struct derived2
{
    struct base super;
    /*derived2 members */
};

void derived2_dance(struct derived2 *pd)
{
    /*implementation of derived2's dance function*/
    printf("derived2 dance\n");
}

void derived2_jump(struct derived2 *pd, int high)
{
    /*implementation of derived2's jump function */
    printf("derived2 jump:%d\n", high);
}

/*global vtable for derived2 */
struct base_vtbl derived2_table =
{
    (void(*)(struct base *))&derived2_dance,
    (void(*)(struct base*, int))&derived2_jump
};
void derived2_init(struct derived2 *pd)
{
    pd->super.vptr = &derived2_table;
    /*init base members d->super.foo */
    /*init derived1 members d->foo */
}


int main(void)
{
    /*OK~! We're done with our declarations, now we can finally do
     * some polymorphism in C
     */
    /*这里类似C++等面向对象语言的构造函数,初始化内存模型,包括了虚函数指针初始化等*/
    struct base b;
    base_init(&b);
    struct base *b_ptr = (struct base*)&b;
    base_dance(b_ptr);
    base_jump(b_ptr, 99);

    struct derived1 d1;
    derived1_init(&d1);

    struct derived2 d2;
    derived2_init(&d2);

    /*这里看作是类型转换,C语言中只有强制转换,或者类型隐式提升,对应于C++的
     * reinterpret_cast,当然C++还有static_cast与dynamic_cast等类型转化
     */

    struct base *b1_ptr = (struct base *)&d1;
    struct base *b2_ptr = (struct base *)&d2;

    /*这里实际上间接引用的就是子类的函数地址*/
    base_dance(b1_ptr); /*calls derived1_dance */
    base_jump(b1_ptr, 88);/*calls derived1_jump */

    base_dance(b2_ptr); /*calls derived2_dance */
    base_jump(b2_ptr, 77); /*calls derived2_jump */

    return 0;
}

从上面运行结果可以看出,C语言实现多态的特性是没有问题的,问题在于我们如何建立抽象模型(实际上类似C++内存对象模型)。而C++恰好原生支持了这一切,不需要我们重复造轮子了。

原文地址: https://blog.csdn.net/sunjunior/article/details/50838143

猜你喜欢

转载自blog.csdn.net/u011956147/article/details/80971695