原文地址http://www.cnblogs.com/kyleada/archive/2011/05/19/2051184.html
可以讓成員函數操作一般化,用基類的指針指向不同的派生類的對象時,
基類指針調用其虛成員函數,則會調用其真正指向對象的成員函數,而不是基類中定義的成員函數(只要派生類改寫了該成員函數)。
若不是虛函數,則不管基類指針指向的哪個派生類對象,調用時都
會調用基類中定義的那個函數。
程序1:
#i nclude <iostream>
using namecpace std;
class B0 //基類B0聲明
{ public:
void display(){cout<<"B0::display()"<<endl;} //公有成員函數
};
class B1: public B0
{
public:
void display(){cout<<"B1::display()"<<endl;}
};
class D1: public B1
{
public:
void display(){cout<<"D1::display()"<<endl;}
};
void fun(B0 *ptr)
{ ptr->display(); //"對象指針->成員名" }
void main() //主函數
{ B0 b0; //聲明B0類對象
B1 b1; //聲明B1類對象
D1 d1; //聲明D1類對象
B0 *p; //聲明B0類指針
p=&b0; //B0類指針指向B0類對象
fun(p);
p=&b1; //B0類指針指向B1類對象
fun(p);
p=&d1; //B0類指針指向D1類對象
fun(p);
}
運行結果:
B0::display()
B0::display()
B0::display()
程序2:
#i nclude <iostream>
using namespace std;
class B0 //基類B0聲明
{public: //外部接口
virtual void display() //虛成員函數
{cout<<"B0::display()"<<endl;}
};
class B1: public B0 //公有派生
{ public:
void display() { cout<<"B1::display()"<<endl; }
};
class D1: public B1 //公有派生
{ public:
void display() { cout<<"D1::display()"<<endl; }
};
void fun(B0 *ptr) //普通函數
{ ptr->display(); }
void main() //主函數
{ B0 b0, *p; //聲明基類對象和指針
B1 b1; //聲明派生類對象
D1 d1; //聲明派生類對象
p=&b0;
fun(p); //調用基類B0函數成員
p=&b1;
fun(p); //調用派生類B1函數成員
p=&d1;
fun(p); //調用派生類D1函數成員
}
運行結果:
B0::display()
B1::display()
D1::display()
虛函數是動態綁定的基礎。
是非靜態的成員函數。
在類的聲明中,在函數原型之前寫virtual。
virtual 只用來說明類聲明中的原型,不能用在函數實現時。
具有繼承性,基類中聲明瞭虛函數,派生類中無論是否說明,同原型函數都自動爲虛函數。
本質:不是重載聲明而是覆蓋。
調用方式:通過基類指針或引用,執行時會 根據指針指向的對象的類,決定調用哪個函數。