對C++ 虛擬函式的理解
阿新 • • 發佈:2019-01-14
今天下午看一個開源專案的原始碼時候,碰到了虛擬函式。為此,就去查資料瞭解一下C++虛擬函式實現機制。
先上程式碼,對著程式碼講。
#include <iostream> #include <stdio.h> using namespace std; class Animal { public: virtual void eat(); // eat 指定為虛擬函式 virtual void sleep(); void work(); // work為非虛擬函式 void run(); }; class Dog: public Animal { public: void eat(); void work(); }; void Animal::eat() { cout << "Aminal eats something" << endl; } void Animal::sleep() { cout << "Animal is sleeping" << endl; } void Animal::work() { cout << "Animal works hardly" << endl; } void Animal::run() { cout << "Aminal is running" << endl; } void Dog::eat() { cout << "Dog eats bone" << endl; } void Dog::work() { cout << "Dog works hardly" << endl; } int main() { Animal* ani = new Dog(); ani -> eat(); ani -> sleep(); ani -> work(); return 0; }
程式中定義兩個類:基類Animal和派生類Dog,也即是父類Animal和子類Dog。
該程式的函式被分為四類:
1.eat函式是虛擬函式,被重新定義
2.sleep函式是虛擬函式,未被重新定義
3.work函式是普通函式,被重寫
4.run函式是普通函式,未被被重寫。
編譯器處理虛擬函式的方法是,對每個類新增一個隱藏成員:一個虛擬函式表(virtual function table, vtbl)。這裡將會建立兩個虛擬函式表。虛擬函式表裡面存放的是每個類中虛擬函式的地址,注意這裡,只存放虛擬函式的地址,不會存放其他成員函式。
程式會使用Dog型別的虛擬地址表,所以,這裡,eat函式會執行子類的eat函式,而sleep仍然會執行父類的sleep函式。而work函式會執行指標的型別,也就是Animal型別。
也就是,對於父類指標指向子類物件的情況來說,除了被重新定義的虛擬函式(eat函式)會執行子類的函式(子類eat函式)之外,其他所有型別的函式都將執行父類函式。
執行結果如下:
Dog eats bone
Animal is sleeping
Animal works hardly
Aminal is running
--------------------------------
Process exited after 0.2431 seconds with return value 0
請按任意鍵繼續. . .
那如果想執行子類Dog的work函式怎麼辦?
強制型別轉換!
將main函式改寫如下:
int main()
{
Animal* ani = new Dog();
ani -> eat();
ani -> sleep();
ani -> work();
ani -> run();
cout << endl;
((Dog*) ani) -> eat();
((Dog*) ani) -> sleep();
((Dog*) ani) -> work();
((Dog*) ani) -> run();
return 0;
}
執行結果如下:
Dog eats bone
Animal is sleeping
Animal works hardly
Aminal is running
Dog eats bone
Animal is sleeping
Dog works hardly
Aminal is running
--------------------------------
Process exited after 0.1338 seconds with return value 0
請按任意鍵繼續. . .
這時候,就和普通的繼承一摸一樣了,哦不是,一模(mu)一樣。
參考:
1. C++ Prime Plus 第六版(中文版)
2.JAVA的多型用幾句話能直觀的解釋一下嗎? - 程式狗的回答 - 知乎 https://www.zhihu.com/question/30082151/answer/120520568