c++基礎(虛擬函式)

Cplusplus-tutorial-in-hindi.jpg
虛擬函式在 c++ 的繼承體系中是一個非常重要概念,讓我們可以在子類中複寫父類的方法。學到這裡我還不知道在 c++ 中是否有抽象類的概念,那麼學習過虛擬函式我們就知道通過(純)虛擬函式可以實現 java 中的抽象類,隨後介紹。
上程式碼通過程式碼進行解釋。
#include <iostream> #include <string> class Shape { public: std::string GetName() { return "Shap"; } }; class Rect : public Shape { private: std::string m_Name; public: Rect(const std::string &name) : m_Name(name) {} std::string GetName() { return m_Name; } }; int main(int argc, char const *argv[]) { Shape *s = new Shape(); std::cout << s->GetName() << std::endl; Rect *r = new Rect("rectangle"); std::cout << r->GetName() << std::endl; std::cin.get(); }
這裡分別定義了 Shape
和 Rect
兩個類,並且 Rect
繼承了 Shape
,同時這兩個類中都有 GetName()
方法。
Shap rectangle
分別呼叫 Shape
的例項 s
和 Rect
的例項· r
的 GetName
輸出如上,正確無誤,是我們想要的效果。
class Rect : public Shape { private: std::string m_Name; public: Rect(const std::string &name) : m_Name(name) {} std::string GetName() { return m_Name; } }; int main(int argc, char const *argv[]) { Shape *s = new Shape(); std::cout << s->GetName() << std::endl; Shape *r = new Rect("rectangle"); std::cout << r->GetName() << std::endl; std::cin.get(); }
向上轉型後發現 Rect 例項 r 的 GetName 輸出為 Shap 而不是 rectangle 。
Shap Shap
void PrintName(Shape *s) { std::cout << s->GetName() << std::endl; } int main(int argc, char const *argv[]) { Shape *s = new Shape(); // std::cout << s->GetName() << std::endl; Shape *r = new Rect("rectangle"); // std::cout << r->GetName() << std::endl; PrintName(s); PrintName(r); std::cin.get(); }
這裡一下程式碼,讓程式碼容易被理解和閱讀,這裡函式 PrintName
接收 Shape
的引用作為引數。
為什麼發生這樣問題,其實也很好理解,我們定義函式 PrintName
接收 Shape
型別的引用做為引數,所以當呼叫 GetName
方法時候就會從 Shape
型別中查詢是否存在該方法然後將其呼叫。
要想讓 Rect
呼叫自己的的 getName
方法而非其父類的 GetName
的方法,就需要使用到虛擬函式,虛擬函式會根據Vtable來進行方法呼叫分配,這樣我們就可以根據型別呼叫到自己的方法。
現在簡單介紹一下,隨後會深入介紹虛擬函式
class Shape { public: virtual std::string GetName() { return "Shap"; } }; class Rect : public Shape { private: std::string m_Name; public: Rect(const std::string &name) : m_Name(name) {} std::string GetName() override { return m_Name; } };
要實現虛擬函式需要兩個步驟進行修改
- 在父類中,在函式
GetName()
前面加上virtual
- 在子類中,在函式
GetName()
後面加上override
再次執行編譯執行程式就得到我們想要結果了
Shap rectangle