zoukankan      html  css  js  c++  java
  • 《挑战30天C++入门极限》C++中类的多态与虚函数的使用

     
     

    C++中类的多态与虚函数的使用

     

    类的多态特性是支持面向对象的语言最主要的特性,有过非面向对象语言开发经历的人,通常对这一章节的内容会觉得不习惯,因为很多人错误的认为,支持类的封装的语言就是支持面向对象的,其实不然,Visual BASIC 6.0 是典型的非面向对象的开发语言,但是它的确是支持类,支持类并不能说明就是支持面向对象,能够解决多态问题的语言,才是真正支持面向对象的开发的语言,所以务必提醒有过其它非面向对象语言基础的读者注意!

      多态的这个概念稍微有点模糊,如果想在一开始就想用清晰用语言描述它,让读者能够明白,似乎不太现实,所以我们先看如下代码:

    //例程1 
    #include <iostream>     
    using namespace std;   
       
    class Vehicle 
    {   
    public:   
        Vehicle(float speed,int total) 
        { 
            Vehicle::speed=speed; 
            Vehicle::total=total; 
        } 
        void ShowMember() 
        { 
            cout<<speed<<"|"<<total<<endl; 
        } 
    protected:   
        float speed; 
        int total; 
    };   
    class Car:public Vehicle   
    {   
    public:   
        Car(int aird,float speed,int total):Vehicle(speed,total)   
        {   
            Car::aird=aird;   
        } 
        void ShowMember() 
        { 
            cout<<speed<<"|"<<total<<"|"<<aird<<endl; 
        } 
    protected:   
        int aird; 
    };   
     
    void main()   
    {   
        Vehicle a(120,4); 
        a.ShowMember(); 
        Car b(180,110,4); 
        b.ShowMember(); 
        cin.get(); 
    }

      在c++中是允许派生类重载基类成员函数的,对于类的重载来说,明确的,不同类的对象,调用其类的成员函数的时候,系统是知道如何找到其类的同名成员,上面代码中的a.ShowMember();,即调用的是Vehicle::ShowMember(),b.ShowMember();,即调用的是Car::ShowMemeber();。

      但是在实际工作中,很可能会碰到对象所属类不清的情况,下面我们来看一下派生类成员作为函数参数传递的例子,代码如下:

    //例程2 
    #include <iostream>     
    using namespace std;   
       
    class Vehicle 
    {   
    public:   
        Vehicle(float speed,int total) 
        { 
            Vehicle::speed=speed; 
            Vehicle::total=total; 
        } 
        void ShowMember() 
        { 
            cout<<speed<<"|"<<total<<endl; 
        } 
    protected:   
        float speed; 
        int total; 
    };   
    class Car:public Vehicle   
    {   
    public:   
        Car(int aird,float speed,int total):Vehicle(speed,total)   
        {   
            Car::aird=aird;   
        } 
        void ShowMember() 
        { 
            cout<<speed<<"|"<<total<<"|"<<aird<<endl; 
        } 
    protected:   
        int aird; 
    };   
     
    void test(Vehicle &temp) 

        temp.ShowMember(); 

     
    void main()   

        Vehicle a(120,4); 
        Car b(180,110,4); 
        test(a); 
        test(b); 
        cin.get(); 
    }

      例子中,对象a与b分辨是基类和派生类的对象,而函数test的形参却只是Vehicle类的引用,按照类继承的特点,系统把Car类对象看做是一个Vehicle类对象,因为Car类的覆盖范围包含Vehicle类,所以test函数的定义并没有错误,我们想利用test函数达到的目的是,传递不同类对象的引用,分别调用不同类的,重载了的,ShowMember成员函数,但是程序的运行结果却出乎人们的意料,iostream>     
    using namespace std;   
       
    class Vehicle 
    {   
    public:   
        Vehicle(float speed,int total) 
        { 
            Vehicle::speed = speed; 
            Vehicle::total = total; 
        } 
        virtual void ShowMember()//虚函数 
        { 
            cout<<speed<<"|"<<total<<endl; 
        } 
    protected:   
        float speed; 
        int total; 
    };   
    class Car:public Vehicle   
    {   
    public:   
        Car(int aird,float speed,int total):Vehicle(speed,total)   
        {   
            Car::aird = aird;   
        } 
        virtual void ShowMember()//虚函数,在派生类中,由于继承的关系,这里的virtual也可以不加 
        { 
            cout<<speed<<"|"<<total<<"|"<<aird<<endl; 
        } 
    public:   
        int aird; 
    }; 
     
    void test(Vehicle &temp) 

        temp.ShowMember(); 

     
    int main()   
    {   
        Vehicle a(120,4); 
        Car b(180,110,4); 
        test(a); 
        test(b); 
        cin.get(); 
    }

      iostream>     
    using namespace std;   
       
    class Vehicle 
    {   
    public:  
        Vehicle(float speed,int total) 
        { 
            Vehicle::speed=speed; 
            Vehicle::total=total; 
        } 
        virtual void ShowMember() 
        { 
            cout<<speed<<"|"<<total<<endl; 
        } 
        virtual ~Vehicle() 
        { 
            cout<<"载入Vehicle基类析构函数"<<endl; 
            cin.get(); 
        } 
    protected:   
        float speed; 
        int total; 
    };   
    class Car:public Vehicle   
    {   
    public:   
        Car(int aird,float speed,int total):Vehicle(speed,total)   
        {   
            Car::aird=aird;   
        } 
        virtual void ShowMember() 
        { 
            cout<<speed<<"|"<<total<<"|"<<aird<<endl; 
        } 
        virtual ~Car() 
        { 
            cout<<"载入Car派生类析构函数"<<endl; 
            cin.get(); 
        } 
    protected:   
        int aird; 
    };   
     
    void test(Vehicle &temp) 

        temp.ShowMember(); 

    void DelPN(Vehicle *temp) 

        delete temp; 

    void main() 
    {   
        Car *a=new Car(100,1,1); 
        a->ShowMember(); 
        DelPN(a); 
        cin.get(); 
    }

      从上例代码的运行结果来看,当调用DelPN(a);后,在析构的时候,系统成功的确定了先调用Car类的析构函数,而如果将析构函数的virtual修饰去掉,再观察结果,会发现析构的时候,始终只调用了基类的析构函数,由此我们发现,多态的特性的virtual修饰,不单单对基类和派生类的普通成员函数有必要,而且对于基类和派生类的析构函数同样重要。

     
     
  • 相关阅读:
    Odoo电子数据交换(EDI)
    WMS8_仓库配置
    odoo写邮件添加收件人
    Odoo HR Payslip
    openERP邮件(发信、收信)
    Multi-company rules
    MRP Force Reservation的作用
    使用虚拟机VM运行Linux版OpenERP
    采购预付款
    消除递归的方法
  • 原文地址:https://www.cnblogs.com/landv/p/11184851.html
Copyright © 2011-2022 走看看