多态


什么是多态?
简单的说:就是用基类的引用指向之类的对象

提问:多态可以用在什么地方呢?
回答:可以用在方法的参数中和方法的返回类型中

实际上就是设计模式中的简单工厂模式!

另外,我我们在JDK中可以大量的看到多态的应用,比如在Object类中的equals(Object obj)方法中,参数是个Object



类型的参数.因为Object是Java中所有类的基类.,但是才传入参数的时候,可以传入任何一个类的对象
这就是多态的应用!

使用多态可以解决项目中紧偶合的问题,提高程序的课扩展性.是OCP原则的一个具体的实现

 

蓝雯飞
c++是以c语言为基础,支持数据抽象和面向对象的程序设计语言。c++对c语言的扩充部分汲取了许多著名语言中最优秀的特征,如从algo168中吸取了操作符重载机制等。由于c++语言具有与c语言一样的高执行效率,并容易被熟悉c语言的软件人员接受,因而很快得以流行。但这种混合型面向对象的程序设计语言是一种新的程序设计语言,人们对它许多潜在的性能(封装、继承、多态等)还没有充分地理解和应用,没有充分发挥其优势。多态性是面向对象系统的重要概念之一,它指的是同样的消息能被发送到父类的对象和它的子类的对象。本文重点讨论多态性在程序设计中的应用。

1 多态性的实现形式

  从广义上说,多态性是指一段程序能够处理多种类型对象的能力。在c++语言中,这种多态性可以通过强制多态、重载多态、类型参数化多态、包含多态4种形式来实现。类型参数化多态和包含多态统称为一般多态性,用来系统地刻画语义上相关的一组类型。重载多态和强制多态统称为特殊多态性,用来刻画语义上无关联的类型间的关系。
  包含多态是指通过子类型化,1个程序段既能处理类型t的对象,也能够处理类型t的子类型s的对象,该程序段称为多态程序段。公有继承能够实现子类型。在包含多态中,1个对象可以被看作属于不同的类,其间包含关系的存在意味着公共结构的存在。包含多态在不少语言中存在,如整数类型中的子集构成1个子类型。每一个子类型中的对象可以被用在高一级的类型中,高一级类型中的所有操作可用于下一级的对象。在c++中公有继承关系是一种包含多态,每一个类可以直接公有继承父类或多个父类,如语句class dpublic p1,public p2{……};表示类d分别是类p1和类p2的子类型。
  类型参数化多态是指当1个函数(类)统一地对若干类型参数操作时,这些类型表现出某些公共的语义特性,而该函数(类)就是用来描述该特性的。在类型参数化多态中,1个多态函数(类)必须至少带有1个类型参数,该类型参数确定函数(类)在每次执行时操作数的类型。这种函数(类)也称类属函数(类)。类型参数化多态的应用较广泛,被称为最纯的多态。
  重载是指用同一个名字命名不同的函数或操作符。函数重载是c++对一般程序设计语言中操作符重载机制的扩充,它可使具有相同或相近含义的函数用相同的名字,只要其参数的个数、次序或类型不一样即可。例如:
  int min(int x,int y);     //求2个整数的最小数
  int min(int x,int y,int z); //求3个整数的最小数
  int min

为了保证在类a中设置的display()函数是抽象动作,并能说明类a是一个抽象的类,在c++中,可用纯的虚函数语言机制在类a中声明1个成员函数“virtual void display(void)=0;”。请注意,在类a的子孙类中要么给出display()的定义,要么重新将该函数声明为纯的。
从上面的分析可以看出,类a的设计尽管是用继承性语法表达的,但它的主要目的不是为代码共享而设计的,而是为了提高多态性而设计的,它是另一个维度的抽象。
2.2 类型参数化多态
  参数化多态又称非受限类属多态,即将类型作为函数或类的参数,避免了为各种不同的数据类型编写不同的函数或类,减轻了设计者负担,提高了程序设计的灵活性。
  模板是c++实现参数化多态性的工具,分为函数模板和类模板二种。
  类模板中的成员函数均为函数模板,因此函数模板是为类模板服务的。类模板在表示数组、表、矩阵等类数据结构时,显得特别重要,因为这些数据结构的表示和算法的选择不受其所包含的元素的类型的影响。下面是一个通用数组类模板的定义。
  template <class t,int n>
  class array
  {t elem[n];
   public:
   array(){for(int j=0;j<n;j++)elem[j]=0;}
   t& operator[](int index){return elem[index];}
  void modi(int index,t value){elem[index]=value;}
  };
  其中,t是类型参数,n是常量参数。t和n的实际值是在生成具体类实例时指定的。类模板的< >可以包括任意个类型参数或常量参数,但至少应有一个参数。在类模板定义中,可在程序中通常使用类型指定的任何地方使用类型参数,可在通常使用特定类型常量表达式的任何地方使用常量参数。
  成员函数模板可放在类模板中定义,也可放在类外定义,例如:
  template <class t,int n>
  t& array<t,n>::operator[](int index){return elem[index];}
  当由类模板生成一个特定的类时,必须指定参数所代表的类型(值)。例如,1个元素类型为int、长度为100的数组类使用类型表达式array<int,100>来表示,这个类型表达式被用于说明数组类对象。例如:
  array<int,100> a: //生成特定类的对象a
  a.modi(1,34);   //对象a访问成员函数
  类模板一旦生成了对象和指定了参数表中的类型,编译器在以后访问数据成员和调用成员函数时完全强制为这些类型。
  在c++中可以重载定义多个同名的函数模板,也可以将1个函数模板与1个同名函数进行重载定义。例如:
  template <class t> t min(t a,t b){return a<b﹖a:b;}
  template <class t>
  t min(t a,t b,t c){t x=min(a,b);return min(x,c);}
  int min(int a,int b)[return a<b﹖a:b;}
  调用min(3,7),则调用第3个函数;调用min(3.8.5.9),编译器将根据带2个参数的模板生成新函数min(double,double);调用min(4,90,76),则编译器根据带3个参数的模板生成新函数min(int,int,int);而调用min(56.3,48,71),编译将给出错误信息,说明无法从上面的模板中生成函数min(double,double,double),因为编译器在类型推导时,不存在类型强制。
  模板描述了1组函数或1组类,它主要用于避免程序员进行重复的编码工作,大大简化、方便了面向对象的程序设计。
2.3 重载多态
  重载是多态性的最简形式,而且把更大的灵活性和扩展性添加到程序设计语言中,它分成操作符重载和函数重载。
  c++允许为类重定义已有操作符的语义,使系统预定义的操作符可操作类对象。c++语言的一个非常有说服力的例子是count对象的插入操作(<<)。由于其类中定义了对位左移操作符“<<”进行重载的函数,使c++的输出可按同一种方式进行,学习起来非常容易。并且,增加一个使其能输出复数类的功能(扩充)也很简单,不必破坏原输出逻辑。
  c++规定将操作符重载为函数的形式,既可以重载为类的成员函数,也可以重载为类的友员函数。用友员重载操作符的函数也称操作符函数,它与用成员函数重载操作符的函数不同,后者本身是类中成员函数,而它是类的友员函数,是独立于类的一般函数。注意重载操作符时,不能改变它们的优先级,不能改变这些操作符所需操作数的个数。
  重定义已有的函数称为函数重载。在c++中既允许重载一般函数,也允许重载类的成员函数。如对构造函数进行重载定义,可使程序有几种不同的途径对类对象进行初始化。还允许派生类的成员函数重载基类的成员函数,虚函数就属于这种形式的重载,但它是一种动态的重载方式,即所谓的“动态联编(束定)”。
2.4 强制多态
  强制也称类型转换。c++语言定义了基本数据类型之间的转换规则,即:
  char->short->int->unsigned->long->unsigned long->float->double->long double
  赋值操作是个特例,上述原则不再适用。当赋值操作符的右操作数的类型与左操作数的类型不同时,右操作数的值被转换为左操作数的类型的值,然后将转换后的值赋值给左操作数。
  程序员可以在表达式中使用3种强制类型转换表达式:①static_cast<t>(e);②t(e);③(t)e。其中任意一种都可改变编译器所使用的规则,以便按自己的意愿进行所需的类型强制。其中e 代表一个运算表达式,t代表一个类型表达式。第三种表达形式是c语言中所使用的风格,在c++中,建议不要再使用这种形式,应选择使用第一种形式。例如,设对象f的类型为double,且其值为3.14。则表达式static_cast<int>(f)的值为3,类型为int。
  通过构造函数进行类类型与其它数据类型之间的转换必须有一个前提,那就是此类一定要有一个只带1个非缺省参数的构造函数,通过构造函数进行类类型的转换只能从参数类型向类类型转换,而想将一个类类型向其它类型转换是办不到的。类类型转换函数就是专门用来将类类型向其它本类型转换的,它是一种类似显式类型转换的机制。转换函数的设计有以下几点要特别注意:①转换函数必须是类的成员函数;②转换函数不可以指定其返回值类型;③转换函数其参数行不可以有任何参数。
  强制使类型检查复杂化,尤其在允许重载的情况下,导致无法消解的二义性,在程序设计时要注意避免由于强制带来的二义性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hhb200766

菩提本无树

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值