文章目录
前言
多态是设计模式的基础,是编写软件框架的基础!
面向对象的三大概念(封装、继承、多态)
一、多态的出现是因为面向对象有了新的需求
现在的编译器的做法不是我们期望的
- 根据实际的对象类型判断重写函数的调用
- 如果父类指针指向是父类对象则调用父类中定义的函数
- 如果子类指针指向是子类对象则调用子类中定义的函数
二、面向对象中的多态
根据实际的对象类型来决定函数调用语句的具体调用目标
p指向父类对象 就运行父类的print()函数
p->print();
p指向子类对象 就运行子类的print()函数
多态:同样的调用语句有多种不同的表现形态
三、c++给我们提过的多态支持方案
- c++中的多态支持
- c++通过virtual关键字对多态进行支持
- 使用virtual声明的函数被重写后可展现多态性
四、实现多态的三个条件
- 要有继承
- 要有虚函数重写
- 用父类指针(父类引用)指向子类对象
五、多态案例分析
class HeroFighter //父类 这块是一代战机
{
public:
virtual int power()//要有虚函数
{
return 10;
}
};
class EnemyFighter //敌机
{
public:
virtual int power()
{
return 15;
}
};
class HeroFighter2 : public HeroFighter //继承 子类继承父类(1)
{
public:
virtual int power()//子类重写父类虚函数(2)
{
return 20;
}
};
//搭建战斗平台
void PlayObj(HeroFighter *hf,EnemyFighter *ef) //用父类指针指向子类对象(3)
{
if(hf->power() > ef->power()) //hf->power() 函数调用
{
cout<<"英雄机获胜"<<endl;
}
else
{
cout<<"敌机获胜"<<endl;
}
}
void main()
{
HeroFigher hf;//创建父类对象 一代战机
EnemyFigher ef;
HeroFigher hf2;//创建子类对象 二代战机
PlayObj(&hf,&ef); //输出结果 敌机获胜
PlayObj(&hf2,&ef); //函数对象 //输出结果 英雄机获胜 也及时这块调用了子类战机
六、多态理论基础
静态联编和动态联编
- c++和c相同,是静态编译型语言
- 在编译时,编译器自动根据指针的类型来判断指向的是一个什么对象,所以编译器认为父类指针指向的是父类对象。
- 由于程序没有运行,所以不可能知道父类指针指向具体是父类对象还是子类对象,从程序的安全角度,编译器假设父类指针只指向父类对象,因此编译结果为调用父类的成员函数,这种特性是静态联编。
联编是指一个程序模块、代码之间相互关联的过程
1、静态联编
静态联编是程序匹配,连接在编译阶段实现的,也称早期匹配,重载函数使用静态联编
不写virtual关键字的就是静态联编
也就是在编译器阶段就已经决定了函数的调用
2、动态联编
动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编(迟绑定)
在运行时候,根据具体对象(具体的类型),去执行不同对象的函数,表现为多态
七、多态原理探究
- 在类中声明虚函数时,编译器会在类中生成一个虚函数表
- 虚函数表是一个存储类成员函数指针的数据结果
- 虚函数表是由编译器自动生成与维护的
- virtual成员函数会被编译器放入虚函数表中
- 存在虚函数时,每个对象中都会有一个指向虚函数表的指针(vptr指针)
class Parent
{
public:
virtual void func()
{
cout<<"parent func()...."<<endl;
}
virtual void func(int i)
{
cout<<"parent func(i)...."<<endl;
}
};
class child :public Parent
{
public :
virtual void func()
{
cout<<"child func()...."<<endl;
}
virtual void func(int i)
{
cout<<"child func(i)...."<<endl;
}
};
重要的补充: 子类vptr指针是分布初始化的
child c1;
当执行父类的构造函数时,c1.vptr先指向父类的虚函数表,当父类构造函数执行完毕后,会把 c1.vptr指向子类的虚函数表
通过虚函数指针vptr调用重写函数是在程序运行时,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。
出于效率考虑,虚函数的效率较低,因此没必要将所有的成员函数都声明成虚函数
多态总结
- 多态实现效果 多态:同样的调用语句有不同的表现形态
- 多态实现3个条件 :1、有继承 2、有virtual重写 3、有父类指针指向子类对象
- 多态c++实现 : virtual关键字,是告诉编译器这个函数要支持多态,根据指针所指向的世纪对象类型来判断如何调用
- 多态理论基础:动态联编:程序运行时,去调用不同对象函数 pk 静态联编:在编译器阶段,就决定怎么调用函数
- 多态是设计模式的基础,是框架的即时
- 多态原理:是c++编译器提前布局了一个vptr指针,通过vptr指针找到一个虚函数表,找到函数的地址,来动态联编(也就是动态的迟绑定)