精华内容
下载资源
问答
  • 多态,多种形态

    2019-04-06 21:49:00
    B这个事物具备了B自己的形态,但是也具备了A的形态。=这就是对象的多态性其实就是,一个对象对应不同的类型代码的体现就是 :父类或者接口的引用指向其子类的对象A b (父类的引用)= new B();(子类的对象) 转载于...

    当子类继承父类时:
    class A {}
    class B  extends A{}
    调用时:B  b=  new  B();
     多态的形式:A b =  new B();
    B这个事物具备了B自己的形态,但是也具备了A的形态。=这就是对象的多态性
    其实就是,一个对象对应不同的类型
    代码的体现就是 :父类或者接口的引用指向其子类的对象
    A b (父类的引用)=  new B();(子类的对象)

    转载于:https://www.cnblogs.com/liyunchuan/p/10663046.html

    展开全文
  • 初识多态的实现形态

    2018-11-10 12:15:54
    今天学习了下多态,做个简单的笔记 ...测试有几表现形态: 1,public static void function(Animal c){ c.sing;}//这样定义显示子类的实现 2,public static void function(Animal c){  Animal c1=new Animal(); ...

    今天学习了下多态,做个简单的笔记

    1,多态里有继承
    2,子类中的多钟形态重载
    3,主程序中定义了父类,实现子类的功能
    测试有几种表现形态:
    1,public static void function(Animal c){
    c.sing;}//这样定义显示子类的实现
    2,public static void function(Animal c){
     Animal c1=new Animal();
    c1.sing;}//此处只能显示父类的实现
    3,public static void function(Animal c){
     Cat6 c1=(Cat6)c;
     c1.catchMouse();//此处好像不能写多个,如定义cat和dog,只能有一个
    }
    4,public static void function(Animal c){
     Cat6 c1=(Cat6)c;
     c1.catchMouse();//此处好像不能写多个,如定义cat和dog,只能有一个
    }
    5,public static void function(Cat6 c){
     Cat6 c1=(Cat6)c;
     c1.catchMouse();//此处好像不能写多个,如定义cat和dog,只能有一个
    }

    class Animal{
     void sing(){
      System.out.println("唱歌");
     }
    }
    class Dog6 extends Animal{
     void sing(){
      System.out.println("汪汪的唱歌");
     }
    }
    class Cat6 extends Animal{
     void sing(){
      System.out.println("喵喵的唱歌");
     }
     void catchMouse(){
      System.out.println("捕鼠");
     }
    }
    public class A651{
     public static void main(String[] args){
      Cat6 c1=new Cat6();
       function(c1);
       Dog6 c2=new Dog6();
       function(c2);
     }
     public static void function(Animal c){//Animal c=new Cat();
      /*Cat6 c1=(Cat6)c;
      c1.catchMouse();
      Dog6 c2=(Dog6)c;
      c2.sing();*///测试好像只能定义cat或者dog,合起来定义程序混乱
      /*Animal c1=new Animal();
        c1.sing//若是定义了Animal,则显示只会显示Animal中的唱歌属性,不会显示子类
    */  c.sing();
     }

    展开全文
  • 多态--多种形态

    2021-07-24 12:30:00
    多态--多种形态 1.概念:父类引用指向子类对象。 注: 父类引用只能调用父类中所定义的属性和方法,子类独有的属性和方法不可调用。 二者必须存在继承关系 2.多态中的方法覆盖: 子类覆盖父类中的方法,使用...

    多态--多种形态
        1.概念:父类引用指向子类对象。
        注:
            父类引用只能调用父类中所定义的属性和方法,子类独有的属性和方法不可调用。
            二者必须存在继承关系
            
        2.多态中的方法覆盖:
            子类覆盖父类中的方法,使用父类引用调用该方法,执行的是覆盖之后的。

        3.好处:
            降低耦合性
            屏蔽子类间的使用差异
            
        4.向上转型、向下转型(掌握)     
        向上转型(装箱):父类引用中保存的是子类对象。
                举例:Animal a = new Dog();
                注意:父类引用只能调用父类中的属性和方法。
                
        向下转型(拆箱):将父类引用中所保存的真实类型强制转换为自身类型。
                举例:Dog d = (Dog)a;
                注意:只有转换为子类真实类型,才可以调用子类中独有属性和方法。

    展开全文
  • 多态多态字面理解为多种多样的形态多态分为静多态与动多态。 静多态: 编译时期的多态:函数重载、模板(函数模板、类模板) 动多态: 运行时期的多态。在继承结构中,基类指针(引用)指向派生类对象,通过该指针...

    一、详解多态应用原理

    多态:多态字面理解为多种多样的形态。多态分为静多态与动多态。
    静多态: 编译时期的多态:函数重载、模板(函数模板、类模板)
    动多态: 运行时期的多态。在继承结构中,基类指针(引用)指向派生类对象,通过该指针(引用)调用同名覆盖方法(虚函数),基类指针指向哪个派生类对象,就会调用哪个派生类对象的同名覆盖方法,成为动多态。多态底层是通过动态绑定来实现的。 基类指针指向谁就访问谁的vfptr,继而继续访问vftable,从vftable拿出来的就是相应的派生类的方法。

    继承的好处:
    1.可以做代码的复用。
    2.在基类中给所有派生类提供统一的虚函数接口,让派生类进行重写,然后就可以使用多态了。

    案例1.静多态:函数重载

    bool compare(int, int){}
    bool compare(double, double){}
    
    compare(10, 20); //call compare_int_int,在编译阶段就确定好调用的函数版本
    compare(10.5, 20.5);//call compare_double_double
    

    案例2.静多态:模板,模板的实例化发生在编译阶段

    template<typename T>
    bool compare(T a, Tb){}
    
    compare(10, 20); //=>int 实例化一个compare<int>
    compare(10.5, 20.5); //=>double 实例化一个compare<double>
    

    案例3.动多态:实现一个动物类
    实现一个动物类:

    //动物基类
    class Animal
    {
    public:
    	Animal(string name):_name(name){}
    	virtual void bark(){}
    protected:
    	string _name;
    };
    
    //动物实体类
    class Cat : public Animal
    {
    public:
    	Cat(string name):Animal(name){}
    	void bark()
    	{
    		cout << _name << "bark:miao miao!" << endl;
    	}
    };
    
    class Dog : public Animal
    {
    public:
    	Dog(string name):Animal(name){}
    	void bark()
    	{
    		cout << _name << "bark:wang wang!" << endl;
    	}
    };
    
    class Pig : public Animal
    {
    	public:
    	Pig(string name):Animal(name){}
    	void bark()
    	{
    		cout << _name << "bark:heng heng!" << endl;
    	}
    };
    
    void bark(Cat &cat)
    {
    	cat.bark();
    }
    
    void bark(Dog &dog)
    {
    	dog.bark();
    }
    
    void bark(Pig &pig)
    {
    	pig.bark();
    }
    
    int main()
    {
    	Cat cat("小猫");
    	Dog dog("小狗");
    	Pig pig("小猪");
    
    	bark(cat);
    	bark(dog);
    	bark(pig);
    
    	return 0;
    }
    

    结构如图:
    在这里插入图片描述
    此时发生动态绑定,但是这个bark()接口不太好,我们若添加更多的新的动物,派生类对象越多,bark()方法还需要继续增加。相应的实体类若删除,其对应接口也要删除,达不到高内聚低耦合。

    那么用什么类型能将上面的对象都能接受呢?
    我们使用统一的基类类型来接受派生类的对象。

    void bark(Animal *p)
    {
    	p->bark();
    }
    

    Cat,Dog,Pig是从Animla继承而来,基类指针就可以指向派生类对象,都可以调用。由于Animal::bark()执行动态绑定,先访问指针指向的对象的前四个字节,基类指针指向了三个不同的对象,每一次访问的就是这三个不同对象的虚函数表,取用它们重写的bark()。

    p->cat cat vftable &Cat::bark();
    p->dog dog vftable &Dog::bark();
    p->Pig pig vftable &Pig::bark();
    

    此时再增加新的派生类型,API接口不用修改,方便许多。
    在这里插入图片描述

    二、抽象类及实例

    抽象类:拥有纯虚函数的类叫做抽象类,我们上面的Animal就是抽象类。
    注意:
    1.抽象类不能再实例化对象了,但是可以定义指针和引用变量。

    抽象类与普通类有什么区别?
          抽象类一般不是用来定义某一个实体类型的,不能实例化对象的,但是可以定义指针和引用变量。它所做的事情是:1.让所有的派生类类通过继承基类直接复用该属性。2.给所有的派生类保留统一的覆盖/重写接口;普通类定义指针,引用变量都可以,实例化对象也可以。

    一般把什么类设计成抽象类?
    基类。 这个基类并不是为了抽象某个实体类型而存在的,它所做的事情是:1.让所有的派生类类通过继承基类直接复用该属性。2.给所有的派生类保留统一的覆盖/重写接口;

    实例1:Animal类
    我们上面定义Animal的初衷,并不是让Animal抽象某个实体的类型。
    1.string_name,让所有的动物实体类通过继承Animal直接复用该属性。
    2.给所有的派生类保留统一的覆盖/重写接口。
    我们的Animal类就是抽象类,virtual void bark()就是纯虚函数。

    //动物基类  泛指  类-》抽象一个实体的类型
    class Animal
    {
    public:
    	Animal(string name):_name(name){}
    	virtual void bark() = 0;//纯虚函数
    protected:
    	string _name;
    };
    

    实例2:Car类
    Car类就是抽象类,virtual double getMilesPerGallon() = 0;就是纯虚函数。

    //汽车的基类,抽象类
    class Car
    {
    public:
    	Car(string name, double oil):_name(name),_oil(oil){}
    	//获取汽车剩余油量还能跑的公里数
    	double getLeftMiles()
    	{
    		//不同汽车1L油跑的公里不一样
    		return _oil * this->getMilesPerGallon();//动态绑定,
    		//基类指针指向不同派生类对象访问不同派生类重写的getMilesPerGallon()
    	}
    	string getName()const
    	{
    		return _name;
    	}
    protected:
    	string _name;
    	double _oil;
    	virtual double getMilesPerGallon() = 0;//纯虚函数,根据具体的汽车而定1L油跑的公里数
    };
    
    class Bnze : public Car
    {
    public:
    	Bnze(string name, double oil):Car(name, oil){}
    	double getMilesPerGallon()
    	{
    		return 20.0;//具体的车跑到公里不一样
    	}
    };
    
    class Audi : public Car
    {
    public:
    	Audi(string name, double oil):Car(name, oil){}
    	double getMilesPerGallon()
    	{
    		return 18.0;//具体的车跑到公里不一样
    	}
    };
    
    class BMW : public Car
    {
    	public:
    	BMW(string name, double oil):Car(name, oil){}
    	double getMilesPerGallon()
    	{
    		return 19.0;//具体的车跑到公里不一样
    	}
    };
    
    //给外部提供一个统一的获取汽车剩余路程数的API
    void showCarleftMiles(Car &car)
    {
    	cout << car.getName() << "left miles:" << car.getLeftMiles() << "公里" << endl;
    }
    
    int main()
    {
    	Bnze b1("奔驰",20.0);
    	Audi a("奥迪",20.0);
    	BMW b2("宝马",20.0);
    	showCarleftMiles(b1);
    	showCarleftMiles(a);
    	showCarleftMiles(b2);
    
    	return 0;
    }
    

    执行一下:执行成功。
    在这里插入图片描述

    展开全文
  • 多态

    2021-05-08 15:56:00
    静态多态(多种形态表现出来): 函数重载 和 运算符重载属于静态多态,复用函数名 动态多态(大部分): 派生类和虚函数实现运行时多态 静态多态和动态多态区别: 静态多态的函数地址早绑定 - 编译阶段...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,951
精华内容 8,780
关键字:

多态的四种形态