虚函数是一种特殊的成员函数,主要用于实现多态。虚函数运行基类指针和应用调用派生类成员函数,从而实现对函数的动态绑定。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Base
{
public:
//构造函数不用许使用虚函数,虚函数在运行时通过虚函数表来实现动态分配,
//构造函数,初始化类对象,她是在对象创建时自动调用,
// 此时虚函数表还没有完全建立,因此无法实现动态分配。
Base() {
cout << "Base Constrouct"<<endl;
}
//声名虚函数时,编译器为其声名了一个虚函数表,
//虚函数表是存储类成员函数指针的数组。
void virtual display()
{
cout << "Base class display function" << endl;
}
/*
* 析构函数声名为虚函数,这样可以确保在删除基类指针指向派生类对象时,
* 派生类析构函数能够被正确调用,避免内存泄露。
*
*/
virtual ~Base()
{
cout << "Base Deconstruct"<<endl;
}
};
class Deviced:public Base
{
public:
Deviced() {
cout << "Deviced Constrouct"<<endl;
}
void display()
{
cout << "Deviced class display function"<<endl;
}
~Deviced()
{
cout << "Deviced Deconstruct"<<endl;
}
};
class Vbase
{
public:
void virtual display() = 0;
};
int main()
{
Base* b = new Deviced();
//Vbase c;纯虚函数不能实例化
//c.display();
//Deviced d;
//b = &d;
b->display();
//基类声名为析构函数,基类指针删除派生类对象时,
// 可以正确调用派生类析构函数,从而避免内存泄露
delete b;
return 0;
}
代码中在Base中声名一个display虚函数,在Deviced类中重写(override)display函数。在主函数中使用一个基类指针指向派生类对象。调用虚函数将执行派生类中覆盖版本。
虚函数实现原理:虚函数的实现主要依靠虚函数表和虚函数指针。
虚函数表:当一个类中声名为虚函数时,编译器会为这个类生成一个虚函数表。虚函数表是一个存储成员函数指针的数组。
虚函数指针:包含虚函数类的对象,都有一个隐藏的成员变量,既虚函数指针(vptr)。对象的虚函数指针,指向其类的虚函数表。当我们通过基类指针调用虚函数时,编译器会根据虚函数指针找到相应的虚函数表,然后再根据虚函数在表中的索引找到并调用相应的虚函数。这个过程发生在运行时,因此实现多态。
构造函数不能声名为虚函数,构造函数不用许使用虚函数,虚函数在运行时通过虚函数表来实现动态分配,构造函数,初始化类对象,她是在对象创建时自动调用,此时虚函数表还没有完全建立,因此无法实现动态分配。
析构函数需要声名为虚函数,析构函数声名为虚函数,这样可以确保在删除基类指针指向派生类对象时,派生类析构函数能够被正确调用,避免内存泄露。
含有虚析构函数运行结果:
不含虚析构函数运行结果:从结果看派生类函数构造切没有释放造成内存泄漏。
虚函数还有很多需要注意,在这里先写这些,以后有机会继续写啦!!!