-
多态性是指统一的接口,不同的表现形式。
2014-09-27 10:35:09多态性是指统一的接口,不同的表现形式。在我们下面的例子中,有5个类。 Game类是Football、Basketball、Popolong的父类,Games类使用前面4个类。 Java根据动态绑定决定执行“更具体”的方法,即子类方法。 ...多态性是指统一的接口,不同的表现形式。在我们下面的例子中,有5个类。
Game类是Football、Basketball、Popolong的父类,Games类使用前面4个类。
Java根据动态绑定决定执行“更具体”的方法,即子类方法。
- //Game.java
- package cn.edu.uibe.oop;
- public class Game {
- protected void play(){
- System.out.println("play game");
- }
- }
- //Football.java
- package cn.edu.uibe.oop;
- public class Football extends Game {
- protected void play() {
- System.out.println("play football");
- super.play();
- }
- void f(){
- play();
- }
- }
- //Basketball.java
- package cn.edu.uibe.oop;
- public class Basketball extends Game{
- protected void play() {
- System.out.println("play basketball");
- }
- }
- //Popolong.java
- package cn.edu.uibe.oop;
- public class Popolong extends Game {
- protected void play() {
- System.out.println("play popolong");
- }
- }
- //Games.java
- package cn.edu.uibe.oop;
- public class Games {
- public static void main(String[] args) {
- Game[] games = new Game[10];
- games[0] = new Basketball();
- games[1] = new Football();
- games[2] = new Popolong();
- for(int i=0;i<games.length;i++){
- if(games[i]!=null)
- games[i].play();
- }
- }
- }
-
多态性
2020-03-05 00:03:00C++程序设计中,多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用同一函数名调用不同的函数。在面向对象方法中一般这样表述多态性:向不同的对象发送同一个消息,不同的对象在接收时会产生不同的行为...C++程序设计中,多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用同一函数名调用不同的函数。在面向对象方法中一般这样表述多态性:向不同的对象发送同一个消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。前面的重载就体现了多态性。
基类指针与派生类指针
- 基类指针可以访问基类对象对应的基类中的所有基类成员和成员函数。
- 基类指针可以访问派生类对象对应的类中,所有从基类中继承的元素。
- 基类指针不能直接访问派生类中的元素,但可以通过强制转换的形式对基类指针进行转换,进而访问派生类元素。
// ch4_1.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string.h> using namespace std; //基类 class A { public: void show_A(){ cout<<"我是类A"<<endl; } }; //派生类 class B : public A { public: void show_B(){ cout<<"我是类B"<<endl; } }; int main() { A *p; B *pb; A a; B b; //基类指针可以访问基类对象对应的基类中的所有基类成员和成员函数。 p = &a; p -> show_A(); //基类指针可以访问派生类对象对应的类中,所有从基类中继承的元素。 p = &b; p -> show_A(); //p -> show_B(); //基类指针不能直接访问派生类中的元素, //但可以通过强制转换的形式对基类指针进行转换,进而访问派生类元素。 ((B *)p)->show_B(); //派生类指针可以直接访问继承的元素 pb = &b; pb -> show_B(); pb -> show_A(); } 结果 我是类A 我是类A 我是类B 我是类B 我是类A
从系统实现的角度看,多态性分为两类:
- 静态多态性:用函数重载实现的多态性。在程序编译时系统就能决定调用的是哪个函数,因此又称编译时多态性。
- 动态多态性:用虚函数实现的多态性。在运行过程中才动态的确定操作对象,又称运行时的多态性。
虚函数
在面向对象的程序设计中,经常会使用类的继承,在多个派生类中保留基类的某些特性,减少开发新类的时间。但有时从基类继承来的某个成员函数不能完全适应派生类的需要,我们可以将其在基类中声明为虚函数(virtual),在派生类中重新定义同名函数并更新其功能,借助基类指针任意调用基类或派生类中的同名函数。
正如上文所说,基类指针不能直接访问派生类中的元素,因此当下面程序调用show()函数时,访问的是派生类从基类中继承的show()函数。
// Ch4_2.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> using namespace std; class Base { public: void show(){cout<<"Base"<<endl;} }; class Derv1 : public Base { public: void show(){cout<<"Derv1"<<endl;} }; class Derv2 : public Base { public: void show(){cout<<"Derv2"<<endl;} }; int main() { Derv1 dv1; Derv2 dv2; Base* pBase; //基类指针 pBase = &dv1; pBase->show(); pBase = &dv2; pBase->show(); return 0; } 结果 Base Base
如果想使用基类指针去任意调用不同类中定义的同名函数,我们可以将基类中的函数声明为虚函数。(自我理解:此时,派生类中的同名函数自动成为虚函数,相当于对基类中函数的重新定义。)因此,再使用基类指针就可以调用派生类中的同名函数了。
class Base { public: virtual void show() { cout<<"Base\n"; } }; 结果 Derv1 Derv2
使用虚函数时值得注意的问题:
- 只能用virtual声明类的成员函数,虚函数的作用是允许在派生类中对基类的虚函数重新定义。显然,它只能用于类的继承层次结构中。不能将类外的普通函数声明为虚函数,也不能将静态成员函数声明为虚函数,因为它不属于某个对象。
- 在派生类中重新定义虚函数,要求除了函数体外都需要与基类的虚函数完全相同,否则就无法实现多态机制。例如。基类中的函数为virtual void show() const,而派生类中的函数为void show() ,这两个函数不是同名函数,关键字virtual不起作用。一般情况下,返回值也应该相同,但有一种例外:当基类函数的返回类型为类指针或引用时,派生类中的虚函数可以返回该类的指针或引用,因此基类与派生类的指针具有兼容性。
- 一个成员函数被声明为虚函数后,在同一类族中就不能再定义一个非 virtual 的但与该虚函数具有相同的参数(包括类型和个数)和函数返回值类型的同名函数。
- 派生类中可以根据需要重新定义虚函数,如果没有对基类的虚函数重新定义,则派生类简单地继承其直接基类的虚函数。如果函数在类外定义,则不能在函数定义中添加 virtual。
什么情况下应该将成员函数定义为虚函数?
- 判断成员函数所在的类是否会作为基类,然后看该函数在类被继承后有无可能被更改功能,如果希望更改其功能,一般应该将它声明为虚函数。
- 判断对成员函数的调用是通过对象名还是通过基类指针或引用去访问,如果是通过基类指针或引用去访问的,则应当声明为虚函数。
注意:
在使用虚函数时,系统要有一定的时间和空间开销。当一个类带有虚函数时,编译系统会为该类构造一个虚函数表(virtual function table,简称vtable),它是一个指针数组,存放每个虚函数的入口地址。
静态关联与动态关联
对于函数的重载,编译器会根据参数的个数和类型,寻找与之匹配的函数版本,调用多个重载函数中的一个。而对于继承体系下同一类族中的同名函数,也需要按照相应的原则告知编译系统,应该调用哪个类对象的成员函数。确定调用的具体对象的过程称为关联或绑定。一般来说,关联指把一个标识符和一个存储地址联系起来。在这里是指把一个函数名与一个类对象捆绑在一起建立关联。
静态绑定:对象名直接调用成员函数。在编译时系统就知道应该调用派生类中的同名函数,函数的调用方式在运行前就已经确定,这种方式称为静态解析或静态关联。函数的重载也属于静态关联。
动态绑定:利用指针调用虚函数。在编译时不知道应该调用基类还是派生类的函数,只有运行时才能根据指针指向对象的类型觉得调用的函数,这种方式称为动态关联或动态绑定。由于动态关联是在编译以后的运行阶段进行的,因此也成为滞后关联或后期关联。
虚析构函数
非成员函数、静态成员函数、内联函数和构造函数不能声明为虚函数。析构函数可以是虚函数,虚析构函数常用于指引 delete 运算符正确析构动态对象。
处理继承类层次结构中动态分配的对象时存在一个问题:如果用 delete 释放指向派生类对象的基类指针,即显式地用该运算符删除每一个对象,不管基类指针所指向的对象是何种类型,系统都会调用基类的析构函数,这种问题有一个简单的解决办法,即将基类析构函数声明为虚析构函数。这样就会使所有派生类的析构函数自动成为需析构函数,尽管它们与基类析构函数名不同。这时,如果使用 delete 运算符释放对象时,系统会调用相应类的析构函数。注意,在删除派生类对象时,同时删除派生类对象的基类部分,基类析构函数在派生类析构函数之后自动执行。
注意:
专业人员一般都习惯声明虚析构函数,即使基类并不需要析构函数,也是显式的定义一个函数体为空的虚析构函数,以保证在撤销动态分配空间时能得到正确的处理。
纯虚函数
有时在基类中将某一成员函数定义为虚函数,并不是基类本身的要求,而是考虑到派生类的需要,在基类中预留一个函数名,具体功能留给派生类根据需要去定义。在基类中函数体为空,即没有实现代码的虚函数为纯虚函数。如果在一个类中声明了纯虚函数,而在其派生类中没有对该函数的定义,则该虚函数在派生类中仍然为纯虚函数。
声明方式:
virtual 函数类型 函数名(参数表列) =0; 例如: virtual void draw() const = 0;
纯虚函数的几个特点:
- 作用是在基类中为其派生类保留一个接口,以便派生类根据需要对它进行定义。
- 如果在基类中没有保留函数名字,则无法实现多态性。
- 纯虚函数只有函数的名字而不具备函数的功能,不能被调用。
- 其只是通知编译系统:在这里声明一个虚函数,留待在派生类中对此函数提供定义后,才能具备功能,可被调用。
抽象类和具体类
- 抽象类:如果类中的一个或多个虚函数声明为纯虚函数,则被类为抽象类。抽象类无法实例化任何对象。抽象类作为基类被其他类继承,所以通常称为抽象基类,其他类可从它这里继承和实现接口。
- 具体类:具有足以能够实例化对象的明确定义。
class Shape //抽象类 { public: Point where() { return center; } virtual void draw() = 0; //纯虚函数 protected: Point center; //Point类对象为数据成员 Shape(const Point& shapePosistion):Point(shapePosistion){} }; Shape x; //error 抽象类不能实例化对象 Shape *p; //ok 声明抽象类的指针 Shape f(); //error 抽象类不能作为返回类型 void g(Shape); //error 抽象类不能作为参数类型 Shape & h(Shape &); //ok 声明抽象类的引用
-
PHP对象中多态性是什么?
2018-10-12 07:44:54多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息将可以产生不同的结果,这种现象称为多态性。 多态性允许每个对象以适合自身的方式去响应共同的消息。多态性...PHP对象中多态性是什么?
from:http://www.cnblogs.com/ricklz/p/9263439.html
多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息将可以产生不同的结果,这种现象称为多态性。
多态性允许每个对象以适合自身的方式去响应共同的消息。多态性增强了软件的灵活性和重用性。 -
python多态性_Python基础之类的多态与多态性
2021-02-10 05:28:42文件有多种形态:文件、文本文件、可执行文件二 多态性(1)什么是多态性(注意:多态与多态性是两种概念)多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象...文件有多种形态:文件、文本文件、可执行文件
二 多态性
(1)什么是多态性(注意:多态与多态性是两种概念)
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
综上可以说,多态性是一个接口(函数func),多种实现(如f.click())
二、为什么要用多态性(多态性的好处)
其实大家从上面多态性的例子可以看出,我们并没有增加上面新的知识,也就是说Python本身就是支持多态性的,这么做的好处是什么呢?
(1)增加了程序的灵活性
以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)
(2)增加了程序额可扩展性
通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用
注:
多态:同一种事物的多种形态,动物分为人类,猪类(在定义角度) 多态性:一种调用方式,不同的执行效果(多态性)
-
C++之多态性
2019-06-05 00:25:31在C++程序设计中,多态性是指用一个名字定义不同的函数,这些函数执行不同但又类似的操作,这样就可以用同一个函数名调用不同内容的函数。换言之,可以用同样的接口访问功能不同的函数,从而实现“一个接口,多种... -
8.1多态性
2019-10-01 02:16:15多态性是指一个名字,多种语义;或界面相同,多种实现。 重载函数是多态性的一种简单形式。 虚函数允许函数调用与函数体的联系在运行时才进行,称为动态联编。 8.1 静态联编 8.1 静态联编 联编是指一个... -
多态与多态性
2019-01-09 21:02:00多态性是指在不考虑实例类型的情况下使用实例,多态性分为静态多态性和动态多态性 静态多态性:如任何类型都可以用运算符+进行运算 动态多态性:如下 class Ainmal: def eat(self): print('吃吃吃')class Pig: ... -
Java多态性
2020-03-06 19:54:55多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。 实现的前提?父类可以引用子类,也叫向上类型转换(upcasting) 机制 使用动态绑定机制(Dynamic binding),下面... -
C# 多态性
2015-11-23 13:31:10在c#中,多态性的定义是:同一个操作作用于不同类的...运行时,多态性是指直到系统运行时才根据实际情况决定实现何种操作,其是通过虚方法来实现的。 虚方法: 通过在方法声明语句的访问修饰符和返回类型之间放置vir -
java多态性
2017-03-08 12:51:06多态性是指同名的若干方法,具有不同的实现,多态性能增强程序的动态特性,使其具备良好的扩展性,多态表现形式有两种: (1) 方法重载:又称为静态多态性,即一个类中允许多个同名方法,对这些同名方法的区分... -
多态性与虚函数
2020-11-19 17:00:22多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容的函数。 函数重载与运算符重载也是一种多态性,不过它们是在程序编译时系统就能决定调用的是哪个函数,因此称为静态多态性。... -
5.2什么是多态性【C++】
2017-12-13 14:52:375.1什么是多态性 在C++程序设计中,多态性是指用一个名字定义不同的函数,这些函数执行不同但又类似的操作,从而可以使用相同的调用方式来调用这些具有不同功能的同名函数。 -
详解C++编程的多态性概念
2021-01-20 05:52:07多态性(polymorphism)是面向...在C ++程序设计中,多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性的:向不同的对象发送同一个消息 -
java的多态性
2016-04-25 21:54:17学了还蛮久的java,一直知道其具备面向对象的三个基本特征:继承、封装和多态...动态多态性是指方法的重写,即多态是指在有继承关系的两个或两个以上的类的行为。下面是一个重写的小Demopublic class DynamicTest { st -
【C++】5.1 编译时的多态性与运行时的多态性
2019-09-20 19:16:02(2)在C++程序设计中,多态性是指用一个名字定义不同的函数,函数执行不同但类似的操作,可以实现用同一个函数名调用不同的内容的函数。“一个接口,多种方法” 2、静态联编和动态联编 【静态联编】: 定义:又... -
C++多态性
2018-03-22 17:10:09多态性是指在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。 1:用...
-
使用cut截取特定的子字符串
-
MySQL 高可用(DRBD + heartbeat)
-
本地伪集群测试Demo
-
html与servlet学习笔记DAY01
-
MySQL 性能优化(思路拓展及实操)
-
思维导图软件
-
实时Twitter流中的自适应进化过滤
-
树莓派使用DHT11实现温度监测
-
2021 年该学的 CSS 框架 Tailwind CSS 实战视频
-
牛牛量化策略交易
-
【Python-随到随学】FLask第二周
-
算法-数据结构-新兵训练营:编码Inteview新兵训练营:算法+数据结构-源码
-
加载序列帧图片并播放
-
中兴刷机工具putty
-
MySQL 主从复制 Replication 详解(Linux 和 W
-
工程制图 AutoCAD 2012 从二维到三维
-
物联网基础篇:快速玩转MQTT
-
pdf2word.exe
-
mysql在阿里云ubuntu服务器的配置过程
-
竞争性编程-源码