总结C++多态(修改中)



     多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。多态(polymorphism),字面意思多种形状。     

      多态性 --指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种多态性:编译时多态性,运行时多态性。相应的存在两种多态实现方式--函数重载和虚函数,函数重载是通过静态联编--在编译的时刻就要确定好使用那种函数(编译时多态性),虚函数是通过动态联编--在程序运行的时刻才指定使用那种函数(运行时多态性)。《多态通过联编(动态联编和静态联编)实现》。多态与非多态的实质区别就是函数地址是早绑定还是晚绑定。如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并生产代码,是静态的,就是说地址是早绑定的。而如果函数调用的地址不能在编译器期间确定,需要在运行时才确定,这就属于晚绑定。

      一般谈多态就是指的通过虚函数实现的多态,(多态是特指虚函数的多态)下面只谈论这种多态。 

     多态的作用:封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用,  那么多态的作用是什么呢?--多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。

     最常见的多态使用方法就是声明一个基类的指针,利用该指针指向任意一个子类对象,就可以根据指向的子类的不同而实现不同的(指虚函数)方法。如果没有使用虚函数的话,即没有利用C++多态性,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,而固定的地址将始终调用到同一个函数,这就无法实现一个接口,多种方法的目的了  。   

     举几个多态形象的例子(不知恰当否):因为父辈不太会使现代通讯产品,所以往往借助后辈来打电话(这是背景)。一个父亲有通讯需求但没有现代的通讯手段(有也很落后),但他有3个儿子(甲乙丙),儿子们都有自己的通讯手段,当父亲某天想要打电话给外出当保姆的孩儿他娘问平安时,他就指定一个比如儿子甲,通过儿子甲的通讯手段满足自己的通讯需求。你们看,这就形象的说明多态的作用,老的对象可以通过指定新对象来获得新对象的方法手段。                               再举一个例子:动物作为一个基类可以派生出老虎、大熊猫等子类,它们都有自己的进食习惯如老虎吃肉,大熊猫吃竹子,当我们要列举动物的进食习惯时我们可以说动物有的吃肉,有的吃竹子(但动物作为一个大类(抽象类),随着新物种的发现它的子类也在不断增加中,所以它也就没办法写死动物的进食方式,而且它本身也无法实例对象化,但他的子类可以产生对象并具有具体的进食习惯,我们可以通过获得子类的进食方式就可以进行列举动物的进食习惯,就算后续增加新物种,我们也可以通过同样指定的方式获得新物种的进食方式。(或者多态这样描述:动物中的老虎吃肉,动物中的大熊猫吃竹子,......)

    C++多态性是通过虚函数来实现的 ,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override) 。虚函数--虚函数是在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态覆盖(Override).     虚函数有纯虚函数和非纯虚函数。

C++纯虚函数和抽象类
 一、定义
  纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”
  virtual void funtion()=0
二、引入原因
   1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
   2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
  为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。                                                       三,抽象类
  包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象

 

c++父类指针指向子类对象

父类子类指针函数调用注意事项
1,如果以一个基础类指针指向一个衍生类对象(派生类对象),那么经由该指针只能访问基础类定义的函数(静态联翩)
2,如果以一个衍生类指针指向一个基础类对象,必须先做强制转型动作(explicit cast),这种做法很危险,也不符合生活习惯,在程序设计上也会给程序员带来困扰。(一般不会这么去定义)
3,如果基础类和衍生类定义了相同名称的成员函数,那么通过对象指针调用成员函数时,到底调用那个函数要根据指针的原型来确定,而不是根据指针实际指向的对象类型确定。

虚函数就是为了对“如果你以一个基础类指针指向一个衍生类对象,那么通过该指针,你只能访问基础类定义的成员函数”这条规则反其道而行之的设计。
如果你预期衍生类由可能重新定义一个成员函数,那么你就把它定义成虚拟函数( virtual )。
polymorphism就是让处理基础类别对象的程序代码能够通透的继续适当地处理衍生类对象。
纯虚拟函数:
virtual void myfunc ( ) =0;
纯虚拟函数不许定义其具体动作,它的存在只是为了在衍生类钟被重新定义。只要是拥有纯虚拟函数的类,就是抽象类,它们是不能够被实例化的(只能被继承)。如果一个继承类没有改写父类中的纯虚函数,那么他也是抽象类,也不能被实例化。
抽象类不能被实例化,不过我们可以拥有指向抽象类的指针,以便于操纵各个衍生类。
虚拟函数衍生下去仍然是虚拟函数,而且还可以省略掉关键字“virtual”。

***************************************************************************************************************************

2 篇笔记     

  1.  

     

    1,纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用。

    2、虚函数声明如下:virtual ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错,错误提示为:

    error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"

    3、对于虚函数来说,父类和子类都有各自的版本。由多态方式调用的时候动态绑定。

    4、实现了纯虚函数的子类,该纯虚函数在子类中就编程了虚函数,子类的子类即孙子类可以覆盖该虚函数,由多态方式调用的时候动态绑定。

    5、虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。

    6、在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。

    7、友元不是成员函数,只有成员函数才可以是虚拟的,因此友元不能是虚拟函数。但可以通过让友元函数调用虚拟成员函数来解决友元的虚拟问题。

    8、析构函数应当是虚函数,将调用相应对象类型的析构函数,因此,如果指针指向的是子类对象,将调用子类的析构函数,然后自动调用基类的析构函数。

     

    9个月前 (08-02)
  2.  

    C++多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数;

    形成多态必须具备三个条件:

    1、必须存在继承关系;

    2、继承关系必须有同名虚函数(其中虚函数是在基类中使用关键字Virtual声明的函数,在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数);

    3、存在基类类型的指针或者引用,通过该指针或引用调用虚函数;

    



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值