谈谈C++中的抽象

转载 2006年05月29日 17:58:00

谈谈C++中的抽象

作者: 李建忠

这两天抽空在审校邓际锋(soloist)先生翻译的Bjarne Stroustrup为Embedded software and systems. 2005写作的《 Abstraction and the C++ machine model》一文。结合自己一段时间的C++培训经验,对C++的抽象有了更多的思考,在此作一简单总结,与朋友们交流。

为了将问题谈清楚,首先来谈谈抽象(Abstraction)这个词,wikipedia对Abstraction有如下解释:

Abstraction is the process of reducing the information content of a concept, typically in order to retain only information which is relevant for a particular purpose.

简单来说,就是“去粗取精”,或者“去不相关,取相关”。

这“一去一取”的目的何在?wikipedia也给了很好的解释:

Complexity reduction

Abstraction typically results in complexity reduction leading to a simpler conceptualization of a domain in order to facilitate processing or understanding of many specific scenarios in a generic way

总体而言,前面摘自wikipedia的两段话非常扼要地说明了“抽象”在我们认识事物过程中所扮演的关键角色——推开来说,人对世界的认识,实际上就是一个不断“抽象”的过程。“抽象”的力量普遍存在于各种学科,各个领域中。当然,具体到各个学科领域还是有一些具体的差别。

好,下面来具体谈谈C++中的抽象,或者说编程语言的抽象。从最根本性的目的来言,计算机就是对人的一种抽象——当然Turing的这个美好愿望要靠程序员来慢慢实现。编程语言在这个过程中扮演的角色就是将 “计算机容易理解的东西”抽象为“人容易理解的东西”。结合目前主流的编程语言(C++, C#, Java, VB.NET 等),举些例子具体来谈其中的抽象,就是让程序员:

基本的编程抽象
* 忘掉数据(无论对象/指针/引用)在内存中的地址,将精力集中在数据所表达的类型实例概念上

面向过程编程的抽象
* 忘掉函数调用的压栈/出栈细节,将精力集中在函数之间的调用关系上

基于对象编程的抽象
* 忘掉对象中数据成员(字段)的内存布局,将精力集中在数据成员对对象状态的表达上
* 忘掉对象中函数成员(方法)的绑定机制以及this指针,将精力集中在函数成员对对象行为的表达上 

面向对象编程的抽象
* 忘掉类继承下子类对象中数据成员的内存布局,将精力集中在继承所带来的子类化的概念上
*忘掉虚函数相关的虚表vTable结构,将精力集中在虚函数所带来的动态多态的概念上 

泛型编程的抽象
* 忘掉模板的各种编译与绑定机制,将精力集中在用一组抽象的概念来表达一组类型的需求条件上

面向组件编程的抽象
* 忘掉组件平台背后的元数据等机制,将精力集中在组件化模块所表达的黑盒概念上

 

这些“忘掉…而将精力集中在…上”的“抽象”放到C#, Java, VB.NET 等其他语言中,很多程序员都可以轻易做到——换句话说,可以不关心“各种抽象背后所映射的底层机器模型”,只关心语言表达的“抽象”,而照样开发出合格甚至优秀的程序。这样,这些语言下的程序员基本上遵循下面的学习路径,就可以成为一个合格的程序员:

掌握语言语法构造–>掌握设计思想(即抽象)–>开发应用程序 或者 程序库

但是如果放到C++,一个程序员无论如何不能够做到“忘掉…而将精力集中在…上”的“抽象”,否则连写出哪怕是正确运行的程序都很难。一个合格的C++程序员必须遵循下面的学习路径:

掌握语言语法构造–>掌握各种抽象所映射的底层机器模型–>掌握设计思想(即抽象)–>开发应用程序 或者 程序库

这就是C++中“抽象”的问题!C++程序员无法摆脱“各种抽象所映射的底层机器模型”而将精力单独集中于“抽象”上——换句话说,C++的抽象性和它的底层性是C++的一体两面,不能够像其他语言一样轻易分开。

那么是什么导致了C++这种独特的“不够彻底的抽象”呢?这种“不够彻底的抽象”到底有什么优劣呢?

Bjarne Stroustrup 在《 Abstraction and the C++ machine model》一文中重复了他在设计C++时一贯的哲学:

* 在切实可行的最高抽象层次上编程 Work at the highest feasible level of abstraction

所谓“切实可行”就是不损及效率,灵活,管理……简单地说就是C++希望在获得“抽象”的同时,仍然尽可能地不损失任何效率。C++一路发展过来,确实达到了这个目标。这正是C++“不够彻底的抽象”之原因。

这种“不够彻底的抽象”当然为C++赢得了巨大的成功,使得C++成为系统级软件的首选语言,是任何其它一门语言都无法望其项背,参见这些重量级的软件http://public.research.att.com/~bs/applications.html

但这也使得C++在程序员圈子里一直是公认的难学难用。孟岩在C++开源程序库评话(节选) 中谈到用C++写优秀的程序库非常难这一事实。可惜只谈了“难”的结论,没有谈“难”的原因。事实上,C++并不仅仅在写程序库时难,用C++写应用程序同样不会轻松–相对其他语言而谈,只是C++写程序库要同时考虑的“抽象性和底层性”思维力度更大罢了。所有的根源都在于C++这种“不够彻底的抽象”。

我不知道“C++的抽象性和底层性这种一体两面的紧密结合”会在多大程度上损伤C++程序员学习的积极性,并从而影响C++应用的popularity,以及影响软件项目的质量和进度。 但至少对于目前希望成为C++程序员的朋友来讲,必须认识到“需要同时掌握C++语言抽象性和底层性”这个事实,才能将C++彻底掌握好,这也是我在目前不管是给企业,还是个人学员讲授C++培训课程时经常强调的。

当然,C++社区也意识到了这个问题,C++0x 也确立了一项“同时为专家和新手提供支持”的原则,参见Bjarne Stroustrup在去年C++软件技术大会上的发言《C++0x概览》。但是从目前来看,这个原则贯彻的并不能令人满意。例如,我不太相信如果一个C++程序员不清楚理解指针,对象,模板,concept(C++0x中的新东西)等所映射的底层机器模型,就能够轻松写出Bjarne在《C++0x概览》一文中最后演示的那个draw_all()的例子——虽然Bjarne Stroustrup期望所有C++程序员都认为它“如此简单!”

也许我们本来就不应该对C++期望太多,既想让它有极致的效率来构造系统软件,又想让它有纯然的抽象来满足变化无常的一般性软件开发——世界上好像没有十全十美的事情,当然也没有十全十美的语言:)

c++ java 抽象工厂模式代码

  • 2016年12月31日 19:20
  • 417KB
  • 下载

C++面向对象的抽象 封装继承 多态总结

根源为总结http://www.cnblogs.com/clongge/archive/2008/07/09/1239076.html 面向对象的编程语言不止仅仅多了个类,类可以明显感觉到抽象和封...

C++ VC++ 设计模式 抽象模式

  • 2011年01月23日 11:13
  • 21KB
  • 下载

关于C++抽象类代码资源

  • 2014年09月07日 15:13
  • 2.08MB
  • 下载

C++抽象编程——算法分析(4)——合并排序算法

然而,对大型vectory要求的排序,选择排序算法显然不符合任务,因为运行时间与输入大小的平方成比例增加,对于以线性顺序处理向量的元素的大多数排序算法也是如此。 所以要采用定性不同的方法来开发更好的排...
  • redRnt
  • redRnt
  • 2017年05月12日 15:29
  • 736

C++数据抽象和问题求解源代码

  • 2016年08月16日 22:11
  • 801KB
  • 下载

C++算法学习——经典的抽象设计——堆—栈模式

如果不绘制大量图片,我们是难以理解内存分配的工作原理。 用于可视化分配过程的最佳工具是 堆—栈 图,其中列出了堆和堆栈上的内存状态。 使用new操作符创建的动态分配的内存显示在图的左侧,表示堆。 每个...
  • redRnt
  • redRnt
  • 2017年06月11日 21:35
  • 496

抽象工厂模式的C++、Java实现

  • 2017年02月04日 21:06
  • 2.09MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:谈谈C++中的抽象
举报原因:
原因补充:

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