第49课 多态的概念和意义

1. 函数重写回顾

(1)父类被重写的函数依然会继承给子类

(2)子类重写的函数覆盖父类中的函数

(3)通过作用域分辨符(::)可以访问到父类中的函数

Child c;

 

Parent* p = &c;

 

c.Parent::print();  //从父类中继承

c.print();          //在子类中重写

 

p->print();         //父类中定义

 

2. 面向对象中期望的行为

(1)根据实际的对象类型判断如何调用重写函数

(2)父类指针(引用)

  ①指向父类对象时,则调用父类中定义的函数

  ②指向子类对象时,则调用子类中定义的重写函数

 

3. 面向对象中多态的概念

(1)根据实际的对象类型决定函数调用的具体目标

(2)同样的调用语句在实际运行时多种不同的表现形态

    

 

(3)C++语言直接支持多态的概念

  ①通过使用virtual关键字对多态进行支持

  ②被virtual声明的函数被重写后具有多态特性

  ③被virtual声明的函数叫做虚函数

 

【编程实验】多态初体验(可对比第48课的非多态版本)

#include <iostream>

#include <string>

 

using namespace std;

 

class Parent

{

public:

   

    virtual void print()  //多态版本,与48课唯一的不同!

    {

        cout << "I'm Parent." << endl;

    }

};

 

class Child : public Parent

{

public:

    void print()  //虚函数,父类己加virtual,这里不必再写

    {

        cout << "I'm Child." << endl;

    }

};

 

void how_to_print(Parent* p)

{

    p->print() ; //展现多态的行为

}

 

int main()

{

    Parent p;

    Child  c;

   

    //多态,根据实际对象类型来调用虚函数

    how_to_print(&p); //I'm Parent.

    how_to_print(&c); //I'm Child.

  

    return 0;

}

 

4. 多态的意义

(1)在程序运行过程中展现出动态的特性

(2)函数重写必须多态实现否则没有意义

(3)多态面向对象组件化程序设计的基础特性

 

5. 理论中的概念

(1)静态联编在程序的编译期间就能确定具体的函数调用(如函数重载

(2)动态联编在程序实际运行后才能确定具体的函数调用(如函数重写

(3)小结

  ①使用父类指针(引用)函数前virtual动态联编没加virtual静态联编

  ②使用父类或子类自身声明对象加不加virtual都是静态联编的

 

【实例分析】动态联编静态联编

#include <iostream>

#include <string>

 

using namespace std;

 

class Parent

{

public:

    virtual void func()

    {

        cout << "Parent: void func()" << endl;

    }

 

    virtual void func(int i)

    {

        cout << "Parent: void func(int i): " << i << endl;

    }

 

    virtual void func(int i, int j)

    {

        cout << "Parent: void func(int i, int j): " << i << ", " << j << endl;

    }

};

 

class Child : public Parent

{

public:

    void func(int i, int j)

    {

        cout << "Child: void func(int i, int j): " << i << ", " << j << endl;

    }

 

    void func(int i, int j, int k)

    {

        cout << "Child: void func(int i, int j, int k): " << i << ", " << j << ", " << k << endl;

    }

};

 

void run(Parent* p)

{

    p->func(1, 2);   //展现多态的特性,动态联编

}

int main()

{

    Parent p;

 

    p.func();     //静态联编

    p.func(1);    //静态联编

    p.func(1, 2); //静态联编

 

    cout << endl;

 

    Child c;

    c.func(1, 2);   //静态联编

 

    run(&p);

    run(&c);

 

    cout << endl;

 

    Parent* p2 = &c;

    p2->func();  //动态联编,virtual函数,尽管func()在Child中没有被重写

 

    return 0;

}

 

 

【编程实验】江湖恩怨

//场景:庄主打老怪

 

#include <iostream>

#include <string>

 

using namespace std;

 

//老怪

class Boss

{

public:

    //无名怪招

    int fight()

    {

        int ret = 10; //威力10

       

        cout <<"Boss::fight(): " << ret << endl;

       

        return ret;

    }

};

 

//老庄主

class Master

{

public:

    //八剑齐飞

    virtual int eightSwordKill()

    {

        int ret = 8; //威力10

       

        cout <<"Master::eightSwordKill(): " << ret << endl;

       

        return ret;

    }

};

 

//少庄主

class NewMaster : public Master

{

public:

    //八剑齐飞

    int eightSwordKill()

    {

        //少庄主对老庄主的八剑齐飞进行改造,练就了双臂的八剑齐飞

        //威力大增

        int ret = Master::eightSwordKill() * 2; //威力是老庄主的2倍

       

        cout <<"NewMaster::eightSwordKill(): " << ret << endl;

       

        return ret;

    }

};

 

//战场pk

void field_pk(Master* master, Boss* boss)

{

    int k = master->eightSwordKill();

    int b = boss ->fight();

   

    if(k < b)

    {

        cout <<"Master is killed..." << endl;

    }

    else

    {

        cout <<"Boss is killed..." << endl;

    }

}

 

int main()

{

    Master master;

    Boss boss;

   

    cout <<"Master vs Boss" << endl;

   

    field_pk(&master,&boss);

   

    cout << endl;

   

    cout <<"NewMaster vs Boss" << endl;

    NewMaster newMaster;

   

    field_pk(&newMaster, &boss);

   

    return 0;

}

/*输出结果

Master vs Boss

Master::eightSwordKill(): 8

Boss::fight(): 10

Master is killed...

 

NewMaster vs Boss

Master::eightSwordKill(): 8

NewMaster::eightSwordKill(): 16

Boss::fight(): 10

Boss is killed...

*/

 

6. 小结

(1)函数重写只可能发生在父类与子类之间

(2)根据实际对象的类型确定调用的具体函数

(3)virtual关键字是C++中支持多态的唯一方式

(4)被重写的虚函数可表现出多态的特性

 

posted @ 2018-12-30 16:55  梦心之魂  阅读(155)  评论(0编辑  收藏  举报