虚函数:
基类中加入关键字virtual的函数
作用:在基类的派生类中可以通过重写虚函数实现对基类虚函数的覆盖。
当基类指针指向派生类对象时,指针调用的函数实际上是调用了派生类的函数。
基类函数中有virtual关键字
输出结果:derived//调用派生类函数
#include <iostream>
using namespace std;
class base
{
public:
base(){}
virtual void print(){cout<<"base"<<endl;}
//void print(){cout<<"base"<<endl;}
};
class derived:public base
{
public:
derived(){}
void print(){cout<<"derived"<<endl;}
};
int main()
{
base *point=new derived();
point->print();
return 0;
}
基类函数中没有virtual关键字
输出结果:base//调用基类函数
#include <iostream>
using namespace std;
class base
{
public:
base(){}
//virtual void print(){cout<<"base"<<endl;}
void print(){cout<<"base"<<endl;}
};
class derived:public base
{
public:
derived(){}
void print(){cout<<"derived"<<endl;}
};
int main()
{
base *point=new derived();
point->print();
return 0;
}
多态实现原理:
虚函数表指针->虚函数表->虚函数地址
类中定义一个虚函数表指针,该指针指向虚函数表,虚函数表中存储虚函数地址。
实例化一个子类对象时,会初始化虚函数指针。(指针存储在对象的内存中)
若子类没有重新定义虚函数的时候,子类从父类中继承了虚函数,所以子类的虚函数表存储和父类相同的虚函数地址。
若子类重新定义虚函数,子类的虚函数表中存储了自己定义的虚函数地址。
虚拟的析构函数:
父类指针指向子类对象,通过delete父类指针释放子类对象
基类的析构函数添加virtual关键字
作用:基类的析构函数不加virtual关键字时,撤销基类指针,不会调用派生类的析构函数而直接调用基类的析构函数,从而不会释放派生类对象构造时占用的内存,造成内存泄漏。(未调用继承类析构函数而导致内存泄露)
实现原理:
父类
子类
父类指针指向子类对象,当delete删除父类指针时,通过指向的子类对象找到子类的虚函数表指针,从而找到虚函数表,再虚函数表中找到子类的虚析构函数,从而使得子类的析构函数得以执行,子类的析构函数执行之后系统会自动执行父类的虚析构函数。
纯虚函数:
抽象类:包含纯虚函数的类是抽象类,不能实例化。纯虚函数在基类中只有声明,只能在子类中实现。
纯虚函数定义形式:
virtual <函数返回类型> <函数名>()=0;
#include<iostream>
using namespace std;
class Virtualbase
{
public:
virtual void Demon() = 0; //prue virtual function
virtual void Base() { cout << "this is farther class" << endl; }
};
//sub class
class SubVirtual :public Virtualbase
{
public:
void Demon() {
cout << " this is SubVirtual!" << endl;
}
void Base() {
cout << "this is subclass Base" << endl;
}
};
void main()
{
Virtualbase* inst = new SubVirtual(); //multstate pointer
inst->Demon();
inst->Base();
// inst = new Virtualbase();
// inst->Base()
system("pause");
return;
}