#include <iostream>
using namespace std;
//多态学习
//分为静态多态和动态多态;
//静态联编和动态联编;
class Animal
{
public:
void speak()
{
cout << "动物在说话" << endl;
}
};
class Cat :public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
};
void doSpeak(Animal & animal)
{
animal.speak();
}
void test01()
{
Cat cat;
doSpeak(cat);
}
//此时调用doSpeak时,参数类型给的是Cat型而不是Animal型,为什么?
//如果发生了继承关系,编译器允许进行类型转换;
//问题:输出的speak到底是哪个?
//输出的是:动物在说话;
//调用doSpeak时,speak函数的地址早就绑定好了,是在Animal类型中的speak;
//早绑定----静态联编。在编译阶段就确定好了地址;
//如果想调用猫的speak,就不能提前绑定好,需要在运行时再绑定地址;
//动态联编,将doSpeak改为虚函数;
//在父类声明虚函数,就发生了多态,在运行时才知道调用的地址;
//什么是多态?父类的引用或指针 执行 子类;
class Animal2
{
public:
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
class Cat2 :public Animal2
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
};
void doSpeak(Animal2 & animal)
{
animal.speak();
}
void test02()
{
Cat2 cat2;
doSpeak(cat2);
}
//输出:小猫在说话;
int main()
{
test01();
test02();
return 0;
}
//为什么要有多态?
/*
C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就
调用派生类的函数;如果对象类型是基类,就调用基类的函数。
虚函数是在基类中定义的,目的是不确定它的派生类的具体行为。例:
定义一个基类:class Animal//动物。它的函数为breathe()//呼吸。
再定义一个类class Fish//鱼 。它的函数也为breathe()
再定义一个类class Sheep //羊。它的函数也为breathe()
为了简化代码,将Fish,Sheep定义成基类Animal的派生类。
然而Fish与Sheep的breathe不一样,一个是在水中通过水来呼吸,一个是直接呼吸空气。所以基类不能确定该如何定义breathe,所以在基类中只定义了一个virtual breathe,它
是一个空的虚函数。具本的函数在子类中分别定义。程序一般运行时,找到类,如果它有基类,再找它的基类,最后运行的是基类中的函数,这时,它在基类中找到的是virtual
标识的函数,它就会再回到子类中找同名函数。派生类也叫子类。基类也叫父类。这就是虚函数的产生,和类的多态性(breathe)的体现。
这里的多态性是指类的多态性。
*/
/*
为什么要有同一种基类,不同的子类?
这些不同的子类可能有相同的属性,或者只是相同的抽象属性;
例如:狗和猫都有毛,耳朵,眼睛,嘴巴。。
但是狗和鱼相比,鱼就没有毛,但是都有东西覆盖在表皮上,这是抽象属性相同。
*/