多态定义
多态是C++面向对象三大特征之一:
多态分为两类:
-
静态多态:函数重载 和 运算符重载属于静态多态,复用函数名
-
动态多态:派生类和虚函数实现运行时多态
静态多态和动态多态区别:
-
静态多态的函数地址早绑定 - 编译阶段确定函数地址
-
动态多态的函数地址晚绑定 - 运行阶段确定函数地址语法
虚函数语法:在函数前添加virtual
virtual void speak()
#include<iostream>
using namespace std;
class animal
{
public:
virtual void speak() //定于虚函数
{
cout << "animal" << endl;
}
};
class cat:public animal
{
public:
void speak()
{
cout << "cat" << endl;
}
};
void dospeak(animal &a)//引用访问虚函数
{
a.speak();
}
int main()
{
cat cat1;
cat1.speak();
dospeak(cat1);//定义了虚函数结果为cat,不然为animal
return 0;
}
总结:
多态满足条件:
-
有继承关系
-
子类重写父类中的虚函数
多态使用条件:
-
父类指针或者引用指向子类对象
-
函数返回值类型、函数名、参数列表完全一样
纯虚函数和抽象类
在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容
因此可以将虚函数改为纯虚函数
纯虚函数语法:virtual 返回值类型 函数名 (参数列表) = 0 ;
当类中有了纯虚函数,这个类也称为抽象类;
抽象类特点:
-
无法实例化对象
-
子类必须重写抽象类汇总的纯虚函数,否者也属于抽象类
#include<iostream>
using namespace std;
class animal
{
public:
virtual void speak() = 0;//纯虚数和抽象类
};
class cat:public animal
{
public:
void speak()
{
cout << "cat" << endl;
}
};
int main()
{
//animal* p = new animal; //报错,无法实例化抽象类
animal* p = new cat;
p->speak();
delete p;
cat cat1;
cat1.speak();
return 0;
}
虚析构和纯虚析构
多态使用时,如果子类有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方法:将父类中的析构代码改为虚析构或者纯虚析构
虚析构和纯虚析构的共性:
-
可以解决父类指针释放子类对象问题
-
都需要有具体的函数实现
虚析构和纯虚析构的区别:
-
如果是纯虚析构,该类属于抽象类,无法实例化对象
虚析构语法:virtual ~类名(){}
纯虚析构语法:
virtual ~类名() = 0;
类名::~类名()
纯虚析构需要声明也需要实现
总结:
虚析构或纯虚析构就是用来解决父类指针释放子类对象
如果子类中没有堆区数据,可以不写为虚析构或纯虚析构
拥有纯虚析构函数的类也属于抽象类
使用纯虚析构时,既要声明又要实现