精华内容
下载资源
问答
  • Java多态性实现方式

    2015-03-23 14:26:50
    Java多态性Java中多态的实现方式: 实现接口 继承父类并进行方法重写 同一个类中进行方法重载

    Java多态性

    Java中多态的实现方式:

    • 实现接口
    • 继承父类并进行方法重写
    • 同一个类中进行方法重载
    展开全文
  • C++——多态性实现机制

    万次阅读 多人点赞 2015-06-24 22:50:06
    C++的多态性实现机制剖析1. 多态性和虚函数#include class animal { public: void sleep() { cout; } void breathe() { cout;

    C++的多态性实现机制剖析

    1. 多态性和虚函数

    #include <iostream.h>
    class animal
    {
    public:
        void sleep()
        {
            cout<<"animal sleep"<<endl;
        }
        void breathe()
        {
            cout<<"animal breathe"<<endl;
        }
    };
    class fish:public animal
    {
    public:
        void breathe()
        {
            cout<<"fish bubble"<<endl;
        }
    };
    void main()
    {
        fish fh;
        animal *pAn=&fh;
        pAn->breathe();
    }
    

    注意,程序中没有定义虚函数。程序执行的结果是什么?答案是输出:animal breathe
    我们在main()函数中首先定义了一个fish类的对象fh,接着定义了一个指向animal类的指针变量pAn,将fh的地址赋给了指针变量pAn,然后利用该变量调用pAn->breathe()。许多学员往往将这种情况和C++的多态性搞混淆,认为fh实际上是fish类的对象,应该是调用fish类的breathe(),输出“fish bubble”,然后结果却不是这样。下面我们从两个方面来讲述原因。
    1、 编译的角度;C++编译器在编译的时候,要确定每个对象调用的函数的地址,这称为早期绑定(early binding),当我们将fish类的对象fh的地址赋给pAn时,C++编译器进行了类型转换,此时C++编译器认为变量pAn保存的就是animal对象的地址。当在main()函数中执行pAn->breathe()时,调用的当然就是animal对象的breathe函数。
    2、 内存模型的角度;我们给出了fish对象内存模型,如下图所示
    这里写图片描述
    我们构造fish类的对象时,首先要调用animal类的构造函数去构造animal类的对象,然后才调用fish类的构造函数完成自身部分的构造,从而拼接出一个完整的fish对象。当我们将fish类的对象转换为animal类型时,该对象就被认为是原对象整个内存模型的上半部分,也就是图1-1中的“animal的对象所占内存”。那么当我们利用类型转换后的对象指针去调用它的方法时,当然也就是调用它所在的内存中的方法。因此,输出animal breathe,也就顺理成章了。
    前面输出的结果是因为编译器在编译的时候,就已经确定了对象调用的函数的地址,要解决这个问题就要使用迟绑定(late binding)技术。当编译器使用迟绑定时,就会在运行时再去确定对象的类型以及正确的调用函数。而要让编译器采用迟绑定,就要在基类中声明函数时使用virtual关键字,这样的函数我们称为虚函数。一旦某个函数在基类中声明为virtual,那么在所有的派生类中该函数都是virtual,而不需要再显式地声明为virtual。

    #include <iostream.h>
    class animal
    {
    public:
        void sleep()        {   cout<<"animal sleep"<<endl;}
        virtual void breathe()  {   cout<<"animal breathe"<<endl;   }
    };
    class fish:public animal
    {
    public:
        void breathe()  {   cout<<"fish bubble"<<endl;}
    };
    void main()
    {
        fish fh;
        animal *pAn=&fh;
        pAn->breathe();
    }

    大家可以再次运行这个程序,你会发现结果是“fish bubble”,也就是根据对象的类型调用了正确的函数。
    那么当我们将breathe()声明为virtual时,在背后发生了什么呢?
    编译器在编译的时候,发现animal类中有虚函数,此时编译器会为每个包含虚函数的类创建一个虚表(即vtable),该表是一个一维数组,在这个数组中存放每个虚函数的地址。对于例1-2的程序,animal和fish类都包含了一个虚函数breathe(),因此编译器会为这两个类都建立一个虚表,如下图所示:
    这里写图片描述
    那么如何定位虚表呢?编译器另外还为每个类的对象提供了一个虚表指针(即vptr),这个指针指向了对象所属类的虚表。在程序运行时,根据对象的类型去初始化vptr,从而让vptr正确的指向所属类的虚表,从而在调用虚函数时,就能够找到正确的函数。对于例1-2的程序,由于pAn实际指向的对象类型是fish,因此vptr指向的fish类的vtable,当调用pAn->breathe()时,根据虚表中的函数地址找到的就是fish类的breathe()函数。
    正是由于每个对象调用的虚函数都是通过虚表指针来索引的,也就决定了虚表指针的正确初始化是非常重要的。换句话说,在虚表指针没有正确初始化之前,我们不能够去调用虚函数。那么虚表指针在什么时候,或者说在什么地方初始化呢?
    答案是在构造函数中进行虚表的创建和虚表指针的初始化。还记得构造函数的调用顺序吗,在构造子类对象时,要先调用父类的构造函数,此时编译器只“看到了”父类,并不知道后面是否后还有继承者,它初始化父类对象的虚表指针,该虚表指针指向父类的虚表。当执行子类的构造函数时,子类对象的虚表指针被初始化,指向自身的虚表。对于例2-2的程序来说,当fish类的fh对象构造完毕后,其内部的虚表指针也就被初始化为指向fish类的虚表。在类型转换后,调用pAn->breathe(),由于pAn实际指向的是fish类的对象,该对象内部的虚表指针指向的是fish类的虚表,因此最终调用的是fish类的breathe()函数。
    要注意:对于虚函数调用来说,每一个对象内部都有一个虚表指针,该虚表指针被初始化为本类的虚表。所以在程序中,不管你的对象类型如何转换,但该对象内部的虚表指针是固定的,所以呢,才能实现动态的对象函数调用,这就是C++多态性实现的原理。
    总结(基类有虚函数):
    1、 每一个类a都有虚表。
    2、 虚表可以继承,如果子类没有重写虚函数,那么子类虚表中仍然会有该函数的地址,只不过这个地址指向的是基类的虚函数实现。如果基类有3个虚函数,那么基类的虚表中就有三项(虚函数地址),派生类也会有虚表,至少有三项,如果重写了相应的虚函数,那么虚表中的地址就会改变,指向自身的虚函数实现。如果派生类有自己的虚函数,那么虚表中就会添加该项。
    3、 派生类的虚表中虚函数地址的排列顺序和基类的虚表中虚函数地址排列顺序相同。
    这里写图片描述

    展开全文
  • 在Java语言中,通过使用方法的重载和重写实现类的多态性。 2.重写(覆盖)是指父子类之间的关系,当子类继承父类中所有可能被子类访问的成员方法时,如果子类的方法名与父类的方法名相同,那么子类就不能继承父类的...

    1.多态性是面向对象程序设计的重要部分。在Java语言中,通过使用方法的重载和重写实现类的多态性。

    2.重写(覆盖)是指父子类之间的关系,当子类继承父类中所有可能被子类访问的成员方法时,如果子类的方法名与父类的方法名相同,那么子类就不能继承父类的方法,这时,称为子类的方法重写了父类的方法。重写体现了子类补充或者改变父类方法的能力。通过重写,可以使一个方法在不同的子类中表现出不同的行为。多态其实不依赖具体类,依赖抽象类和接口,接下来附上一个例子:

    目录结构:


    Animal.java文件:

    package tom.bean;
    
    /*
     * 定义一个动物类,作为父类
     */
    public class Animal {
    	public Animal(){	//无参构造方法
    	}
    	
    	public void eat(){	//eat()方法
    		System.out.println("动物吃东西");
    	}
    }
    


    Dog.java文件:

    package tom.bean;
    
    /*
     * 定义一个狗类,作为动物类的子类,继承动物类
     */
    public class Dog extends Animal{
    	public Dog(){	//无参构造方法
    	}
    	
    	public void eat(){	//eat()方法,重写了Animal类的eat()方法
    		System.out.println("狗吃狗粮");
    	}
    }
    


    Cat.java文件:

    package tom.bean;
    
    /*
     * 定义一个猫类,作为动物类的子类,继承动物类
     */
    public class Cat extends Animal{
    	public Cat(){	//无参构造方法
    	}
    	
    	public void eat(){	//eat()方法,重写了Animal类的eat()方法
    		System.out.println("猫吃猫粮");
    	}
    }
    

    Tiger.java文件:

    package tom.bean;
    
    /*
     * 定义一个Tiger老虎类,继承Animal动物类
     */
    public class Tiger extends Animal {
    }
    



    Test.java文件,测试类:

    package tom.test;
    
    import tom.bean.Cat;
    import tom.bean.Dog;
    import tom.bean.Tiger;
    
    /*
     * 测试类,打印输出信息
     */
    public class Test {
    	public static void main(String[] args){
    		Dog dog=new Dog();//创建Dog类的对象
    		System.out.println("执行dog.eat();语句后的结果:");
    		dog.eat();//调用eat()方法
    		Cat cat=new Cat();//创建Cat类的对象
    		System.out.println("执行cat.eat();语句后的结果:");
    		cat.eat();//调用eat()方法
    		Tiger tiger=new Tiger();//创建Tiger对象
    		System.out.println("执行tiger.eat();语句的结果:");
    		tiger.eat();//调用eat()方法,此时调用的是父类的eat()方法
    	}
    }
    


    运行Test.java文件后,结果为:

    从上面的例子可以知道,Dog类和Cat类都重写了父类的eat()方法,所以执行的是子类的eat()方法,但是Tiger类没有重写父类的方法,所以执行的是父类中的eat()方法。

    3.方法的重载是指在一个类中出现多个方法名相同,但参数个数或参数类型不同的方法,则称为方法的重载。Java语言在执行该具有重载关系的方法时,将根据调用参数的个数和类型区分具体执行的是哪个方法。下面给出一个例子:定义一个Shape类,在类中定义两个名称为getArea()的方法(参数个数不同)和两个名称为draw()的方法(参数类型不同):

    Shape.java文件:

    package tom.bean;
    
    public class Shape {
    	final float PI=3.14159f;//定义一个用于表示圆周率的常量PI
    	
    	public float getArea(float r){	//定义一个用于计算面积的方法getArea(),求圆形的面积
    		float area=PI*r*r;
    		return area;
    	}
    	
    	public float getArea(float length,float width){	//重载getArea()方法,用来求矩形的面积,重载方法带的参数个数不同
    		float area=length*width;
    		return area;
    	}
    	
    	//画任意形状的图形
    	public void draw(int num){	//定义一个用于画图的方法draw()
    		System.out.println("画一个"+num+"个任意形状的图形");
    	}
    	
    	//画指定形状的图形
    	public void draw(String shape){	//重载draw()方法,重载方法中带的参数类型不同
    		System.out.println("画一个"+shape);
    	}
    	
    	//主方法
    	public static void main(String[] args){
    		Shape shape=new Shape();//创建Shape类的对象
    		float l=10;//声明一个常量,初始化为10,表示矩形的长
    		float w=20;//声明一个常量,初始化为20,表示矩形的宽
    		float rectangleArea=shape.getArea(l, w);//获得矩形的面积,并赋予rectangleArea
    		System.out.println("长度为"+l+",宽度为"+w+"的矩形面积为:"+rectangleArea);//打印输出矩形的面积
    		float r=5;
    		float circleArea=shape.getArea(r);
    		System.out.println("半径为"+r+"的圆形的面积为:"+circleArea);
    		shape.draw(3);//调用draw()方法
    		shape.draw("圆锥");
    	}
    }
    

    运行此程序,结果为:

     

    注:重载的方法直接并不一定必须有联系,但是为了提高程序的可读性,一般只重载功能相似的方法,在进行方法的重载时,方法返回值的类型不能作为区分方法的标志!

    4.以上就是通过方法的重写和重载实现类的多态性,仅供大家学习参考,写得不好,请见谅,如有错误请指出,谢谢!

    
    展开全文
  • C#多态性基础实现

    千次阅读 热门讨论 2014-02-09 17:45:35
    编译时的多态性:编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。 运行时的多态性:运行时的多态性就直到运行时,才根据实际情况实现何...

          多态分为两种情况,一种是编译的时候的多态性,一种是运行时的多态性。

          编译时的多态性:编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。

          运行时的多态性:运行时的多态性就直到运行时,才根据实际情况实现何种操作。C#中运行时的多态性是通过复写虚函数实现的。


          C#中的,多态人们很不容易分清楚。明明是一个相同的名称,而调用起来,却出现了不同的结果。现在来通过一个例子来体会一下多态是如何实现的。

                       

          子类继承父类得到的方法,可以通过重写来覆盖。这样父类的实例就可以使用子类的方法。

     class Program
        {
            static void Main(string[] args)
            {
                fruit ep;                      //定义一个水果的实例
                ep= new Apple();
                ep.AddFruit(5);
                ep = new Orange();
                ep.AddFruit(4);
            }
        }
    
        public abstract class fruit     //创建一个抽象类-水果
        {
            private uint nint_Weight;
            public abstract void AddFruit(uint nWeight);
        }
        public class Apple : fruit         //创建水果的子类-苹果
        {
            public override void AddFruit(uint nWeight)
            {
                Console.WriteLine("你添加了一个苹果,质量为{0}",nWeight);
            }
        }
        public class Orange : fruit       //创建水果的子类-橘子
        {
            public override void AddFruit(uint nWeight)
            {
                Console.WriteLine("你添加了一个橘子,质量为{0}", nWeight);
            }
        }
    

                  


          继承:当子类继承父类的时候,子类可以不用重新定义父类中的方法,可以直接使用。

          多态:当子类重写父类的方法时。父类的对象,调用子类的方法时候,会根据情况来选择基类的方法。


    展开全文
  • √ JavaSE - 怎么实现多态性

    万次阅读 2021-04-11 15:19:21
    1、多态性基于类的继承和方法的重写,使用父类变量指向子类对象,编译时调用父类被重写的方法,运行时执行子类重写的方法,因此多态性发生于运行时。 2、对于重载,编译器在方法调用之前就确定所要调用的方法,称为...
  • 多态性有哪些,怎么实现

    千次阅读 2018-07-23 21:20:06
    C++的多态性:在基类的函数前加上virtual关键字,在派生类中重写该函数,指相同的对象收到不同的消息或者不同的对象收到相同的消息时产生的不同的实现动作。如果对象类型是派生类,就调用派生类的函数;如果对象类型...
  • C++多态性实现方法: C++多态性是通过虚函数实现的。虚函数允许子类重新定义基类的成员函数。 实现方法有两种:重载和重写(也称覆盖)如果你想学习C/C++可以来这个群,首先是三三零,中间是八五九,最后是七六...
  • JAVA中多态性的理解(下)...错误类型代码:代码运行结果二、强制类型转换方法——总结(一)二、强制类型转换方法——总结(二)三、关键字instanceof的使用四、关于属性和方法多态性中的调用总结五、结尾 前言 首
  • java运行时多态性实现

    千次阅读 2015-04-15 17:15:02
    Java实现运行时多态性的基础是动态方法调度,它是一种在运行时而不是在编译期调用重载方法的机制,下面就继承和接口实现两方面谈谈java运行时多态性实现。    一、通过继承中超类对象引用变量引用子类对象...
  • C++ 多态性实现方式

    千次阅读 2013-11-04 18:03:29
    C + + 中多态性实现方式  多态性是面向对象程序设计的一大支柱,它指的是在基类中定义的属性或服务被派生类继承之后,可以表现出不同的行为. 也就是指一段程序能够处理不同类型对象的能力. 在面向对象程序...
  • Java多态性实现机制

    千次阅读 2010-08-01 11:29:00
    通过将子类对象引用赋值给超类对象变量, 来实现动态方法调用。  java 的这种机制遵循一个原则:当超类对象引用变量, 引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这...
  • 多态性(虚方法) 1、在父类的方法中加入virtual,这个方法可以被子类重新写一遍。 在子类的方法前加入override,  static void Main(string[] args)  {  teacher te = new teacher("teache_w");  student st =...
  • 一、方法多态性 (1)方法的重载 定义:同一个方法名可以根据参数列表的不同调用不同的方法体 (2)方法的覆写 定义:同一个父类的方法,可以根据实例化子类的不同也有不同的表现 二、对象的多态性 前提:...
  • (2)在C++程序设计中,多态性是指用一个名字定义不同的函数,函数执行不同但类似的操作,可以实现用同一个函数名调用不同的内容的函数。“一个接口,多种方法” 2、静态联编和动态联编 【静态联编】: 定义:又...
  • 理解误区——方法的重载是多态性的一种体现? 方法的重载是多态性的一种体现吗? 其实这是一个误区,让我很长的一段时间都理解错了,直到又一次系统复习Java的时候才理解,方法的重载并不是是多态性的一种体现. 什么...
  • Java:Java静态多态性与动态多态性

    千次阅读 2014-10-11 17:18:08
    动态多态性指在运行中才能动态确定操作指针所指的对象,主要通过虚函数和重写来实现。 java 的多态机制遵循一个原则:当父类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员...
  • 多态性

    千次阅读 2018-04-16 21:23:27
    在面向对象的设计中,多态...( 多态:在同一个时刻,体现出来的不同状态)多态性主要体现在两个方面:方法重载实现的静态多态性(编译时多态) 方法重写实现的动态多态性(又称动态连编)编译时多态:在编译阶段...
  • C++之多态性

    万次阅读 多人点赞 2019-06-05 00:25:31
    在面向对象方法中,所谓多态性就是不同对象收到相同消息,产生不同的行为。在C++程序设计中,多态性是指用一个名字定义不同的函数,这些函数执行不同但又类似的操作,这样就可以用同一个函数名调用不同内容的函数。...
  • 先来说说java方法的调用,方法的调用不等于方法执行,方法调用阶段唯一的任务是确定被调用方法的版本(即调用哪个方法,不是唯一的,确定一个“更加合适”的版本),不涉及方法内部的具体运行过程。 我们都是知道...
  • 多态性(一)——静态多态性

    千次阅读 2015-03-04 12:18:55
    在面向对象方法中,一般是这样表述多态性的:向不同的对象发送同一个消息,不同的对象在接收时会产生不同的行为。在C++中,多态性表现形式之一是:具有不同功能的函数可以用同一个函数名,这样就可以实现用一个函数...
  • Java面向对象编程——多态性实现

    千次阅读 2017-12-18 20:41:13
    Java中多态性实现 一、使用父类类型的引用指向子类的对象 二、该引用只能调用父类中定义的方法和变量; 三、如果子类中重写了父类中的一个方法,那么在调用这个方法的 时候,将会调用子类中的这个方法;(动态...
  • 文章目录一、多态性二、鸭子类型三、绑定方法1、问题引入2、绑定给类的方法四、非绑定方法 一、多态性 多态指的是一类事物有多种形态,比如动物有多种形态:猫、狗、猪 class Animal: # 同一类事物:动物 def talk...
  • 方法解析 Class文件的编译过程中不包含传统编译中的连接步骤,一切方法调用在Class文件里面存储的都只是符号引用,而不是方法在实际运行时内存布局中的入口地址。这个特性给Java带来了更强大的动态扩展能力,使得...
  • Java运行时多态性实现

    千次阅读 2004-10-15 10:47:00
    Java运行时多态性实现 中国建设银行 郑志远 运行时多态性是面向对象程序设计代码重用的一个最强大机制,动态性的概念也可以被说成“一个接口,多个方法”。Java实现运行时多态性的基础是动态方法调度,它是一种...
  • 使用模板实现多态性

    千次阅读 2007-09-06 12:13:00
    在C++中我们一般采用虚函数的方式实现函数的多态性实现运行期绑定。实际上我们也可以用模板来实现函数的多态性,这在ATL中大量使用的,请看如下的代码:templatetypename T,typename Deriving>class Array...{...
  • 浅谈C++多态性

    万次阅读 多人点赞 2012-04-18 22:45:14
     多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。多态(polymorphisn),字面意思多种形状。  C++多态性是通过虚函数来实现的,虚函数允许子类重新...
  • Class文件的编译过程中不包含传统编译中的连接步骤,一切方法调用在Class文件里面存储的都只是符号引用,而不是方法在实际运行时内存布局中的入口地址。这个特性给Java带来了更强大的动态扩展能力,使得可以在类运行...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 164,472
精华内容 65,788
关键字:

多态性的实现方法