设为首页 加入收藏

TOP

1.4.3 多态与递归
2013-10-07 15:26:41 来源: 作者: 【 】 浏览:78
Tags:1.4.3

1.4.3   多态与递归

熟练掌握多态是成为C++(www.cppentry.com)高手的最重要的条件。多态有多种不同用法,本小节我们探讨其中的一种用法,以此向大家展示面向对象语言在解决某些问题时表现出来的与面向过程语言的不同特性。

例1-3

考虑如何打印列表中的所有元素。给定列表L如下:

(n1,(n2, n3, n4), n5)

L有三个元素:第一个元素为n1;第二个元素是一个子列表(n2, n3, n4),该子列表又拥有三个元素;第三个元素为n5。如果用过程语言如C语言来完成这个任务,那么设计一个用来打印像L这样的列表(即列表包含任意级数的嵌套子列表)的函数,通常需要引入递归机制。程序清单1-2表示一个完成上述功能的C函数,其中Element是描述列表元素的结构,该结构包含用于描述元素是单一的节点还是一个子列表的信息:isNode,若isNode为1,该元素为节点;若isNode为0,该元素为子列表。若元素为子列表,结构中的成员firstElement指向子列表的第一个元素。尽管程序比较短,但其实现逻辑却相当复杂。递归函数因为需要复杂困难的逻辑而难于编写。

程序清单1-2   在C语言中使用递归来处理嵌套子列表

 
 
 
图1-4   类层次中的Object、Node与List类

现在考虑用如图1-4所示的类层次结构来完成上述问题。在这个类层次中,Object类是父类,Node与List是子类,一个列表中的元素可以是Object类层次的某种对象,也就是说,一个列表是由Node对象与List对象组成的集合体,假设Object、Node与List类都拥有一个多态方法print,用来完成正确的打印任务。例如Node类的print函数仅打印节点的内容,List类的print函数循环调用该列表中所有元素的print函数,这样就保证列表中所有的元素,包括子列表中的元素,都能正确地打印出来。程序清单1-3表示用C++(www.cppentry.com)语言实现的List类的多态方法print。List::print这个语法包含一个域解析操作符(scope resolution operator),即两个冒号::。域解析操作符的左边是类名List,右边是函数名print。之所以需要域解析操作符是因为可能存在多个相同函数签名的print。该函数还包括一个const关键字,表明这个函数不会修改这个对象中的任何数据成员(见第3章)。我们假设List类有HasMoreElements和NextElement成员函数,用来对列表中的元素进行迭代,不管这些元素是节点还是子列表,HasMoreElement函数的返回类型是布尔值。如果返回true,表示列表中尚有未处理的元素;如果返回false,表示列表中的元素已经处理完毕。NextElement函数返回一个指针,指向列表中的下一个元素。

程序清单1-3   List类的多态方法print

 

变量obj的数据类型为Object*,而Object是Node和List类的父类,因此,obj可以指向Object类层次中的任何对象。当通过语句
 

调用多态方法print时,系统首先判断obj实际指向对象的类型。本例中,obj可以指向某个Node对象或List对象,一旦对象的类型得到确定,系统将调用相应的函数,即Node::print或List::print。当obj指向一个子列表时,产生的效果相当于在List::print中递归地调用了其自身。不过此处的语法相当简洁,因为递归调用是隐式地而非显式地。此处的要点是,决定调用哪个print是系统而非程序员的责任。如程序清单1-2所示的C程序例子中,程序员必须判断当前的列表元素是节点还是子列表,而在多态版本的例子中,我们将这种判断任务留给了系统,这样就大大地简化了代码编写任务。 

程序清单1-3中List::print的实现逻辑比程序清单1-2中printList的实现逻辑简单得多。这就反映了面向对象编程(www.cppentry.com)中的多态机制可以消除显式的递归调用从而避免了面向过程方法表现出来的复杂逻辑。多态的用途还有很多,我们将在第5章详细讨论这些用法。类及其层次设计中最具挑战性的任务就是设计多态方法,通过这些方法,可以极大地简化客户端的编程(www.cppentry.com)任务。

需要指出的是,面向对象的一些机制如多态并不能消除程序的复杂性。无论使用什么语言进行设计,复杂的问题总是需要复杂的程序,当采用面向对象机制可以将程序的复杂性进行某些形式的分散处理,而很多形式都是过程语言所不具备的。以List::print为例,多态机制使得我们在对列表中的元素进行迭代处理时,将决定是调用Node::print还是List::print这个任务转交给了系统。我们的代码变得简单了,但是程序的复杂程度还是与用C语言实现的递归函数相同。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇1.3.1 客户/服务器模式 下一篇1.2.4 课后练习

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Announcing October (2025-12-24 15:18:16)
·MySQL有什么推荐的学 (2025-12-24 15:18:13)
·到底应该用MySQL还是 (2025-12-24 15:18:11)
·进入Linux世界大门的 (2025-12-24 14:51:47)
·Download Linux | Li (2025-12-24 14:51:44)