C51 蜂鳴器程式設計
阿新 • • 發佈:2021-01-30
技術標籤:# C/C++
首先:強調一個概念
定義一個函式為虛擬函式,不代表函式為不被實現的函式。
定義他為虛擬函式是為了允許用基類的指標來呼叫子類的這個函式。
定義一個函式為純虛擬函式,才代表函式沒有被實現。
定義純虛擬函式是為了實現一個介面,起到一個規範的作用,規範繼承這個類的程式設計師必須實現這個函式。
假設我們有下面的類層次:
class A
{
public:
virtual void foo()
{
cout<<"A::foo() is called"<<endl;
}
};
class B :public A
{
public:
void foo()
{
cout<<"B::foo() is called"<<endl;
}
};
int main(void)
{
A *a = new B();
a->foo(); // 在這裡,a雖然是指向A的指標,但是被呼叫的函式(foo)卻是B的!
return 0;
}
這個例子是虛擬函式的一個典型應用,通過這個例子,也許你就對虛擬函式有了一些概念。它虛就虛在所謂"推遲聯編"或者"動態聯編"上,一個類函式的呼叫並不是在編譯時刻被確定的,而是在執行時刻被確定的。由於編寫程式碼的時候並不能確定被呼叫的是基類的函式還是哪個派生類的函式,所以被成為"虛"函式。
虛(virtual)函式是為了實現多型,派生類可以覆寫(override)基類的虛擬函式。
1、多型(polymorphism),即基類指標或者引用,可能指向基類物件,也可能指向派生類物件,會根據執行時具體指向的物件,來呼叫不同的函式。
2、如果沒有多型,則什麼型別的指標或者引用,就會呼叫什麼型別的物件的函式。
class Animal {
public:
// 編譯時靜態繫結
void print1() {
printf("print1 parent class.\n");
}
// 虛擬函式,告訴編譯器,執行時動態繫結。
virtual void print2() {
printf("print2 parent class.\n");
}
virtual void print3() {
printf("print3 parent class.\n");
}
};
class Dog: public Animal {
public:
void print1() {
printf("print1 Dog class.\n");
}
void print2() {
printf("print2 Dog class.\n");
}
};
Animal *pAni;
Dog dog;
pAni = &dog;
pAni->print1();
pAni->print2();
pAni->print3();
輸出:
print1 parent class.
print2 Dog class.
print3 parent class.
3、每個包含虛擬函式的類(也叫虛類),都有一個虛擬函式表(簡稱虛表),表項是一個虛擬函式的地址。
4、如果基類是虛類,則繼承類也是虛類。
5、虛類的物件最前面都是一個虛表指標,指向類的虛表。