C++ Virtual關(guān)鍵字的具體使用
基礎(chǔ)理解和demo
普通的繼承
#include<iostream> class Parent { public: void print() { std::cout << "Parent" << std::endl; } }; class Child : Parent { public: void print() { std::cout << "Child" << std::endl; } }; int main() { Child c; c.print(); return 0; }
輸出結(jié)果為 "Child"
但是如果是 "父類的指針指向子類的對(duì)象" 這種情況下, 使用這個(gè)父類的指針去調(diào)用被重寫的方法呢, 結(jié)果會(huì)是什么呢? 從語(yǔ)法的本質(zhì)上講, 子類對(duì)象的內(nèi)存前半部分就是父類, 因?yàn)榭梢詫⒆宇悓?duì)象的指針直接轉(zhuǎn)化為父類。
#include<iostream> class Parent { public: void print() { std::cout << "Parent" << std::endl; } }; // 注意這里必須是 public Parent // 不然會(huì)報(bào)錯(cuò) cannot cast 'Child' to its private base class 'Parent' class Child : public Parent { public: void print() { std::cout << "Child" << std::endl; } }; int main() { Parent* p = new Child(); p->print(); return 0; }
這個(gè)時(shí)候輸出的是 "Parent"
。
所以, 當(dāng)一個(gè)成員函數(shù)需要被子類重寫, 那么必須將其聲明為virtual, 也就是 虛函數(shù) , 注意, 子類覆寫的方法的virtual關(guān)鍵字會(huì)自動(dòng)繼承而來(lái), 可以顯示地寫或者不寫(建議還是寫上)。
這樣修改完就沒問題了:
#include<iostream> class Parent { public: virtual void print() { std::cout << "Parent" << std::endl; } }; class Child : public Parent { public: virtual void print() { std::cout << "Child" << std::endl; } }; int main() { Parent* p = new Child(); p->print(); return 0; }
加深理解
Virtual 關(guān)鍵字的一個(gè)重要概念 "只有在通過基類指針或引用間接指向派生類子類型時(shí)多態(tài)性才會(huì)起作用" , 也就是說(shuō), 基類的函數(shù)調(diào)用如果有virtual則根據(jù)多態(tài)性調(diào)用派生類的,如果沒有virtual則是正常的靜態(tài)函數(shù)調(diào)用,還是調(diào)用基類的。
舉個(gè)例子
#include <iostream.h> class Base { public: virtual void f(float x){ cout << "Base::f(float) " << x << endl; } void g(float x){ cout << "Base::g(float) " << x << endl; } void h(float x){ cout << "Base::h(float) " << x << endl; } }; class Derived : public Base { public: virtual void f(float x){ cout << "Derived::f(float) " << x << endl; } void g(int x){ cout << "Derived::g(int) " << x << endl; } void h(float x){ cout << "Derived::h(float) " << x << endl; } }; void main(void) { Derived d; Base *pb = &d; Derived *pd = &d; // Good : behavior depends solely on type of the object pb->f(3.14f); // Derived::f(float) 3.14 pd->f(3.14f); // Derived::f(float) 3.14 // Bad : behavior depends on type of the pointer pb->g(3.14f); // Base::g(float) 3.14 pd->g(3.14f); // Derived::g(int) 3 (surprise!) // Bad : behavior depends on type of the pointer pb->h(3.14f); // Base::h(float) 3.14 (surprise!) pd->h(3.14f); // Derived::h(float) 3.14 }
粘貼這個(gè)博客的一段話, 表達(dá)的就是這個(gè)意思:
bp 和dp 指向同一地址,按理說(shuō)運(yùn)行結(jié)果應(yīng)該是相同的,而事實(shí)上運(yùn)行結(jié)果不同,所以他把原因歸結(jié)為C++的隱藏規(guī)則,其實(shí)這一觀點(diǎn)是錯(cuò)的。決定bp和dp調(diào)用函數(shù)運(yùn)行結(jié)果的不是他們指向的地址,而是他們的指針類型。 “只有在通過基類指針或引用間接指向派生類子類型時(shí)多態(tài)性才會(huì)起作用”(C++ Primer 3rd Edition)。pb是基類指針,pd是派生類指針,pd的所有函數(shù)調(diào)用都只是調(diào)用自己的函數(shù),和多態(tài)性無(wú)關(guān),所以pd的所有函數(shù)調(diào)用的結(jié)果都輸出Derived::是完全正常的;pb的函數(shù)調(diào)用如果有virtual則根據(jù)多態(tài)性調(diào)用派生類的,如果沒有virtual則是正常的靜態(tài)函數(shù)調(diào)用,還是調(diào)用基類的,所以有virtual的f函數(shù)調(diào)用輸出Derived::,其它兩個(gè)沒有virtual則還是輸出Base::很正常啊 ,nothing surprise! 所以并沒有所謂的隱藏規(guī)則,雖然《高質(zhì)量C++/C 編程指南》是本很不錯(cuò)的書,可大家不要迷信哦。記住“只有在通過基類指針或引用間接指向派生類子類型時(shí)多態(tài)性才會(huì)起作用”。
到此這篇關(guān)于C++ Virtual關(guān)鍵字的具體使用的文章就介紹到這了,更多相關(guān)C++ Virtual關(guān)鍵字內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++運(yùn)行時(shí)獲取類型信息的type_info類與bad_typeid異常
- 詳解C++編程中的sizeof運(yùn)算符與typeid運(yùn)算符
- 一文讀懂c++之static關(guān)鍵字
- C/C++ 中const關(guān)鍵字的用法小結(jié)
- 詳解c++中的 static 關(guān)鍵字及作用
- C++面試基礎(chǔ)之static關(guān)鍵字詳解
- C++11關(guān)于auto關(guān)鍵字的使用示例
- c++使用正則表達(dá)式提取關(guān)鍵字的方法
- C++中volatile關(guān)鍵字及常見的誤解總結(jié)
- C++ override關(guān)鍵字使用詳解
- c++ typeid關(guān)鍵字的使用
相關(guān)文章
C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之二叉樹的非遞歸后序遍歷算法
這篇文章主要介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之二叉樹的非遞歸后序遍歷算法的相關(guān)資料,希望通過本文能幫助到大家,讓大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10Visual Studio 2022 的安裝和創(chuàng)建C++項(xiàng)目(圖文教程)
本文主要介紹了Visual Studio 2022 的安裝和創(chuàng)建C++項(xiàng)目,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05Qt實(shí)現(xiàn)定時(shí)器的兩種方法分享
這篇文章主要為大家詳細(xì)介紹了Qt中實(shí)現(xiàn)定時(shí)器的兩種不同方法,文中的示例代碼講解詳細(xì),對(duì)我們了解Qt有一定的幫助,感興趣的可以跟隨小編一起學(xué)習(xí)一下2022-11-11基于C++實(shí)現(xiàn)BMI身體質(zhì)量指數(shù)計(jì)算工具
BMI(Body?Mass?Index,身體質(zhì)量指數(shù)),也稱為體重指數(shù),是一種常用的衡量成人人體肥胖程度的指標(biāo),本文就來(lái)用C++編寫一個(gè)簡(jiǎn)單的BMI計(jì)算工具吧2023-10-10C++靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)文件的生成和使用教程
庫(kù)文件是計(jì)算機(jī)上的一類文件,可以簡(jiǎn)單的把庫(kù)文件看成一種代碼倉(cāng)庫(kù),它提供給使用者一些可以直接拿來(lái)用的變量、函數(shù)和類,下面這篇文章主要給大家介紹了關(guān)于C++靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)文件的生成和使用的相關(guān)資料,需要的朋友可以參考下2023-03-03