一、多态的基本概念
多态:父类的指针或引用,指向或初始化子类的对象,调用子类对父类重新的函数,进而展开子类的功能。
函数重新的必要条件:
- 必须有继承关系
- 子类和父类有同名同类型的函数
- 父类中的该函数必须是虚函数
虚函数:
在函数前加上virtual修饰,即为虚函数。
虚函数满足继承,即父类中的某函数为虚函数,继承到子类中,子类中的该函数依然为虚函数,如果子类再被继承,其子类中的该函数仍旧是虚函数。
virtua 函数返回值类型 函数名(参数列表)
{
函数体;
}
二、多态中函数重写的原理
若类中存在虚函数,则类中就会有一个虚指针,虚指针满足继承。虚指针指向虚函数表,虚函数表中记录了虚函数,包括父类的虚函数,子类对父类重写的函数。
三、虚析构函数
当父类实例化的指针指向子类时,若释放该指针,则仅仅释放该指针指向的子类从父类继承的内容,而子类中原先存在的空间并未得到释放,会造成内存泄漏。此时就需要通过虚析构函数来解决。
虚析构函数定义格式:
virtual ~类名()
{
}
当父类的析构函数为虚析构函数时,释放父类的指针,内存泄漏问题得以解决。
#include <iostream>
using namespace std;
//封装 人 类
class Person
{
private:
string name;
public:
Person() {}
//有参构造函数
Person(string n):name(n){}
virtual ~Person() //虚析构函数 满足继承
{
cout << "Person::析构函数" << endl;
}
};
//封装 学生 继承于人
class Stu:public Person
{
private:
int id;
public:
Stu(){}
//有参构造
Stu(string n , int i):Person(n),id(i){}
~Stu()
{
cout << "Stu::析构函数" << endl;
}
};
int main()
{
Person *p = new Stu("张三",1001);
delete p; //如果没有虚析构函数,进行释放p是,子类自己拓展的空间就没有释放--内存泄漏
p = nullptr;
return 0;
}
四、纯虚函数及抽象类
当父类中的虚函数没有实际意义时,可将该虚函数设置为纯虚函数,含有纯虚函数的类被称为抽象类,抽象类不能实例化对象,当子类没有对父类的纯虚函数进行重新时,子类也被称为抽象类。
纯虚函数定义格式:
virtual 函数返回值类型 函数名(形参列表) = 0; //纯虚函数
示例:
#include <iostream>
using namespace std;
//..
class A //抽象类
{
private:
int a;
public:
A() {}
virtual void show() = 0; //纯虚函数
};
class B:public A
{
public:
B() {}
void show() //如果子类没有对父类的纯虚函数重写,那么子类也是抽象类,不能实例化一个对象
{}
};
int main()
{
B b;
return 0;
}