多态

为什么会出现多态???

赋值兼容性原则遇上函数重定义的时候就出现了问题。

 

重定义重写重载,傻傻分不清楚是吧。补充一下:

重定义重写重载

 

函数重载
  必须在同一个类中进行
  子类无法重载父类的函数,父类同名函数将被名称覆盖
  重载是在编译期间根据参数类型和个数决定函数调用
函数重写
  必须发生于父类与子类之间
  并且父类与子类中的函数必须有完全相同的原型
  使用virtual声明之后能够产生多态(如果不使用virtual,那叫重定义)
多态是在运行期间根据具体对象的类型决定函数调用

好啦,理解了什么是重写后,下面来看看这段代码。

#include "iostream"
using namespace std;

//定义一个子类和一个父类
class Parent
{
public:
    Parent(int a = 0)
    {
        this->a = a;
    }
    void print()
    {
        cout<<"父类a:"<<a<<endl;
    }
protected:
private:
int a; 
};

class Child : public Parent
{
public:
Child(int b = 0)
{
this->b = b;
}

void print()
{
cout<<"子类b:"<<b<<endl;
}
protected:
private:int  b;
};

//面向对象新需求

//如果我传一个父类对象,执行父类的print函数

//如果我传一个子类对象,执行子类的printf函数

 

//现象产生的原因

//赋值兼容性原则遇上函数重写出现的一个现象

//1 没有理由报错

//2 对被调用函数来讲,

//3 在编译器编译期间,我就确定了,这个函数的参数是p,是Parent类型的。。。

 

//静态链编
void HowToPrint1(Parent *p)
{
    p->print(); //一句话,有多种效果,有多种表现形态把。。。//这个功能的就是多态
}
void HowToPrint2(Parent &myp)
{
    myp.print();
}
void main()
{
    Parent p1;
    Child c1;
    /*
    p1.print();
    c1.print();

    
    Parent *p = NULL;
    p = &p1;
    p->print(); //调用父类的打印函数

    ////赋值兼容性原则 遇上 同名函数的时候 
    p = &c1; 
    p->print(); //

    Parent &myp = c1;
    myp.print(); 
    */


    HowToPrint1(&p1);//调用父类的
    HowToPrint1(&c1);//调用父类的

    HowToPrint2(p1);//调用父类的
    HowToPrint2(c1);//调用父类的


    system("pause");
}

 

根据输出结果,我们发现。。始终调用父类的函数!!!这不科学啊。这不是我想要的结果啊!!

于是,多态就出现了。

多态的理解

角度1

p->print(); //一句话,有多种效果,有多种表现形态把。。。//这个功能的就是多态

角度2

面向对象新需求

编译器的做法不是我们期望的

根据实际的对象类型来判断重写函数的调用

如果父类指针指向的是父类对象则调用父类中定义的函数

如果父类指针指向的是子类对象则调用子类中定义的重写函数

 

C++提供的多态解决方案

  • C++中的多态支持
  • C++中通过virtual关键字对多态进行支持
  • 使用virtual声明的函数被重写后即可展现多态特性

 

多态实例

#include "iostream"
using namespace std;

class HeroFighter
{
public:
    virtual int Power()
    {
        return 10;
    }

};

class AdvHeroFighter : public HeroFighter
{
public:
    int Power()
    {
        return 20;
    }
protected:
private:
};

class Adv2HeroFighter : public HeroFighter
{
public:
    int Power()
    {
        return 30;
    }
protected:
private:
};

class EnemyFighter
{
public:
    int attack()
    {
        return 15;
    }
protected:
private:
};
void main()
{
    HeroFighter hf;
    EnemyFighter  ef;
    AdvHeroFighter advHf;
    

    if (hf.Power() < ef.attack())
    {
        cout<<"英雄挂了。。。"<<endl;
    }
    else
    {
        cout<<"英雄win。。。"<<endl;
    }
    if (advHf.Power() < ef.attack())
    {
        cout<<"英雄2挂了。。。"<<endl;
    }
    else
    {
        cout<<"英雄2win。。。"<<endl;
    }
    system("pause");
}

有没有发现一个神奇的地方啊??

//写了一个框架,可以调用我的第3代战机代码出现的时间晚于框架出现的时间框架。。。 有使用后来人 写的代码的能力。。。

//面向对象3大概念
封装-------》突破了C语言函数的概念。。
继承 ------》代码复用 。。。。我复用原来写好的代码。。。
多态-------》多态可以使用未来。。。。。80年代写了一个框架。。。。。。90人写的代码

多态既然这么神奇,那我们怎么实现它呢???

 

多态成立的三个条件

//1 要有继承

//2 要有函数重写。。。虚函数

//3 要有父类指针(父类引用)指向子类对象

//相当于你的框架把。。。。
void ObjPlay(HeroFighter *pBase, EnemyFighter *peEf)
{
    //多态的存在
    if (pBase->Power() < peEf->attack())
    {
        cout<<"英雄挂了。。。"<<endl;
    }
    else
    {
        cout<<"英雄win。。。"<<endl;
    }
}

void main()
{
    HeroFighter hf;
    EnemyFighter  ef;
    AdvHeroFighter advHf;
    Adv2HeroFighter  adv3Hf;

    ObjPlay(&hf, &ef);
    ObjPlay(&advHf, &ef);
    ObjPlay(&adv3Hf, &ef);

}

 

多态工程意义

1、 工程中大量应用,可以做框架

2、 可以架构上,解耦合。。。。

 

 

 

 

posted @ 2016-11-15 12:04  ren_zhg1992  阅读(107)  评论(0)    收藏  举报