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

原创 2016年03月09日 21:02:36

        C++语言演化过程中,加入了不少新特性,使其成为一门现代高级OO语言。当初C++在上个世纪七十年代末,80年代初时,C++发展刚刚起步,那时C++可以看作C with class,C++编写的代码是经过转换成C语言代码后,再经过C编译器来生成目标代码的。如今,C++语言已经自成一套体系,有自己语言书写风格和设计理念。C++整个语法体系中包括了C++基础(兼容C语言语法特性,OO特性)、模板库&STL和泛型编程等知识。由于C++学习时间成本高(目前可以看编程语言排行榜就知道,这门语言流行度在下降,正被其他语言追赶,比如最近流行的python与javascript),一般人要熟练掌握其大部分特性都得3~5年时间。其实现在大部分品牌公司目前停留在了C with Class阶段,简单点说就是用C++这门语言来作产品类封装和搭建框架,其他特性也是不推荐使用的,更别提C++11和C++17后新增加的特性了。


      这里我简单表明下自己对C++语言的看法:个人学习成本与时间成本在如今项目开发中是不得不考虑的问题,在现有计算机体系结构下,CPU执行效率与内存空间大小一般情况下不是开发的瓶颈(某些嵌入式领域除外)。若开发项目时,要在运行效率与开发时间长短上作选择的话,一般公司肯定以开发时间效率高的语言作为首选。C++走的是另外一条统一路线,想一门语言做成所有的事情,结果是语言越来越臃肿,运行效率方面比不上C语言,开发效率又跟不上如今的java,python等语言。前段时间,公司内网上有个博客牛人写了篇博客,深入探讨了C++与C之间的联系与区别,C++语言内部模块耦合太强,也就是说,即使你没有用这个特性,C++在链接的时候,由于语言模块内部依赖性问题也会编译到目标代码中去。一个简单的hello world程序,C++目标文件大小会比C语言大十几K。目前,一般成熟的产品,如果考虑效率高的,一般就直接用C语言来写了,比如nginx,redis,libevent等。再比如类Unix操作系统(linux)大部分代码也是由C语言写的。目前流行的那几种语言,就是因为学习成本低,入手快而被广大程序员所接受。当然就我目前所了解的,不少游戏公司驱动引擎还是由C++写的,某些大型嵌入式产品也会考虑用C++来做。同时目前市场上也有不错的第三方C++库,比如boost,QT,ACE等库,我曾经一段时间用QT写过不少客户端程序来支撑公司测试和维护某一类路由器产品,尤其QT中引入QtQuick特性后,开发时间上也提升了不少,帮助公司节省了25~30%的时间成本。


       下面回到正题,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++恰好原生支持了这一切,不需要我们重复造轮子了。

C语言实现多态

综述 多态性是面向对象程序设计的一个重要特征,利用多态性可以设计和实现一个易于扩展的系统。 顾名思义,多态的意思是多种形态,在C++程序设计中,多态指的是:具有不同功能的函数可以用同一个函数名,这样可...

C语言实现多态?

c语言实现多态。c++的多态分为两种: 1.编译时多态:重载 2.运行时多态:重写(也称为覆盖override)C++实现函数重载,依据的是不同的函数签名(与返回值无关,函数名+函数参数列表决定,...

c语言实现多态

转载自:http://www.cnblogs.com/haippy/archive/2012/12/31/2840501.html 上面一篇博客中写了《如何实现 C 的函数重载》,本...

如何用C语言实现类似C++中的多态

先引用一篇博文,讲讲什么是多态: C++编程语言是一款应用广泛,支持多种程序设计的计算机编程语言。我们今天就会为大家详细介绍其中C++多态性的一些基本知识,以方便大家在学习过程中对此能够有一个充分的...

C++特性的C语言实现(1)继承

阅读文章之前应当有一定的汇编、C和C++的基础。 面向对象的程序设计有三大特性:封装、继承和多肽。 这里只讨论后两种特性继承和多肽,因为C++中封装性实际上是由编译器去识别关键字public、priv...

C语言面向对象编程(一):封装与继承

C++ 语言中自带面向对象支持,如封装、继承、多态等面向对象的基本特征。 C 原本是面向过程的语言,自身没有内建这些特性,但我们还是可以利用 C 语言本身已有的特性来实现面向对象的一些基本特征。接下来...
  • foruok
  • foruok
  • 2014年01月12日 22:16
  • 42737

C语言实现面向对象的思想

用C语言实现面向对象的方法,面向对象的三个基本特征,对象唯一性,继承性,抽象性。 使用C语言中的结构体和函数指针将数据与操作放在一起,使得一个问题的解决方法封装在结构体中。 其中结构体的嵌套使用实现了...

C语言面向对象编程(五):单链表实现

这里实现的单链表,可以存储任意数据类型,支持增、删、改、查找、插入等基本操作...
  • foruok
  • foruok
  • 2014年01月21日 08:54
  • 7503

浅谈C++多态性

C++编程语言是一款应用广泛,支持多种程序设计的计算机编程语言。我们今天就会为大家详细介绍其中C++多态性的一些基本知识,以方便大家在学习过程中对此能够有一个充分的掌握。   多态性可以简单地概括为“...

c++面向对象三大特征封装、继承和多态知识总结

面向对象三大特征:封装,继承,多态; 一、封装:该公开的就公开话,该私有的就隐藏掉,主要是由public,private实现;作用是便于分工和分模块,防止不必要的扩展; 二、继承:就是一种传承,可以把...
  • uestclr
  • uestclr
  • 2016年06月05日 18:23
  • 2626
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C语言实现C++面向对象语言多态特性
举报原因:
原因补充:

(最多只允许输入30个字)