C++虚函数工作原理:声明虚函数的类中会有一个隐藏变量(所以会多4个字节),主要指向虚函数地址的表。如果子类没有重写父类的虚函数,子类中的虚函数地址表中该虚函数地址跟父类一样,如果重写了父类的虚函数,则该虚函数地址则为新的。如果一个函数没有申明为虚函数,编译器会进行静态联编,如果改行申明为虚函数,编译器则进行动态联编。所以在程序运行时,发现调用的函数是虚函数时,会在对象的虚函数表中查找该函数的地址。

 看以下例子:

#include<iostream>
using namespace std;
class A
{
public:
    void Print(){cout<<"A"<<endl;}
};
class B:public A
{
public:
    void Print(){cout<<"B"<<endl;}
};
class C
{
public:
    virtual void Print(){cout<<"C"<<endl;}
};
class D:public C
{
public:
    void Print(){cout<<"D"<<endl;}
};
int main()
{
    B b;
    D d;
    A &a = b;
    a.Print();
    //输出是A,静态联编
    C &c = d;
    c.Print();
    //输出是D,动态联编,通过虚函数表查找函数地址
    return 0;
}

 一个函数的析构函数最好申明为虚函数,不然很有可能导致资源泄露

#include<iostream>
#include<cstdio>
using namespace std;
class A
{
public:
    A(){cout<<"A"<<endl;}
    ~A(){cout<<"~A"<<endl;}
};
class B:public A
{
public:
    B(){cout<<"B"<<endl;}
    ~B(){cout<<"~B"<<endl;}
};
class C
{
public:
    C(){cout<<"C"<<endl;}
    virtual ~C(){cout<<"~C"<<endl;}
};
class D:public C
{
public:
    D(){cout<<"D"<<endl;}
    ~D(){cout<<"~D"<<endl;}
};
int main()
{
    A *a = new B();
    delete a;
    /*没有调用B的析构
    A
    B
    ~A
    */
    C *c = new D();
    delete c;
    /*
    A
    B
    ~B
    ~A
    */
    return 0;
}

 C++ 子类写父类的函数叫重写,即使参数不一样或者名字不一样,都叫重写。父类如果有3个函数,void fun(),void fun(int) ,void fun(int,int);子类即使重写了void fun()这一个函数,父类的void fun(int),void fun(int,in)在子类中也被隐藏,所以每次子类重写父类函数时,需要把父类所有重载的函数都要写一遍。