面向对象的程序设计都有
封装,继承和多态
三大特性,前两个特性在之前的博客中已经提到,这篇主要讲关于C++多态问题。
何为多态?
简单的说,就是一句话:
允许将子类类型的
指针
(引用)赋值给父类类型的指针(引用)。
举个例子,当我们在定义两个类,一个Person类作为父类,在乘坐高铁时购买二等座,Boss是Person的派生类,乘车购买一等座,而且他们的购票成员函数名字相同,如以下代码:
class Person
{
public:
void Dis(void) {
cout << "Second-class seat" << endl;
}
};
class Boss :public Person
{
public:
void Dis(void) {
cout << "First-class seat" << endl;
}
};
在写一个Fun函数传入两个类型的实例化对象对其成员函数进行调用时,我们将Fun的参数类型仅设置为Person的引用,看看能不能实现多态,即自动区分两个实例化对象,对其买票做出正确的输出
#include <iostream>
using namespace std;
class Person
{
public:
void Dis(void) {
cout << "Second-class seat" << endl;
}
};
class Boss :public Person
{
public:
void Dis(void) {
cout << "First-class seat" << endl;
}
};
void Fun(Person& p)
{
p.Dis();
}
int main()
{
Person p;
Fun(p);
Boss b;
Fun(b);
return 0;
}
运行起来后发现程序没有对其进行区分…
那么将要引入多态的形成条件:
-
虚拟成员函数的重写
-
调用虚函数函数的参数类型为父类指针/引用
虚拟成员函数的重写到底是说明概念呢?我们之前都了解到过函数的重载,函数的重定义,下边归纳一下这三个概念:
函数的重载:在同一作用域当中,函数名相同,参数不同构成重载
函数的重写(覆盖规则):子类成员的虚拟函数与父类成员的虚拟成员函数完全一样
函数的重定义(同名隐藏规则):子类成员函数与父类成员函数名相同
我们根据规则将代码进行改动
#include <iostream>
using namespace std;
class Person
{
public:
virtual void Dis(void) {
cout << "Second-class seat" << endl;
}
};
class Boss :public Person
{
public:
virtual void Dis(void) {
cout << "First-class seat" << endl;
}
};
void Fun(Person& p)
{
p.Dis();
}
int main()
{
Person p;
Fun(p);
Boss b;
Fun(b);
return 0;
}
这时候就产生了我们的预期效果,也就是利用实例化出来的对象就可以直接用父类指针或者引用函数进行操作,会实现自动找到各自的成员虚拟函数。
下一篇博客将会对C++多态原理以及虚表的概念进行分析,请在博客目录中翻阅浏览