C++中的虛函數(virtual function)

2020-12-08 太平洋電腦網

正在閱讀:C++中的虛函數(virtual function)C++中的虛函數(virtual function)

2005-07-15 10:36出處:作者:unknow責任編輯:moningfeng

一.簡介

   虛函數是C++中用於實現多態(polymorphism)的機制。核心理念就是通過基類訪問派生類定義的函數。假設我們有下面的類層次:

class A
{
public:
virtual void foo() { cout << "A::foo() is called" << endl;}
};

class B: public A
{
public:
virtual void foo() { cout << "B::foo() is called" << endl;}
};


  那麼,在使用的時候,我們可以:

A * a = new B();
a->foo(); // 在這裡,a雖然是指向A的指針,但是被調用的函數(foo)卻是B的!


  這個例子是虛函數的一個典型應用,通過這個例子,也許你就對虛函數有了一些概念。它虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並不是在編譯時刻被確定的,而是在運行時刻被確定的。由於編寫代碼的時候並不能確定被調用的是基類的函數還是哪個派生類的函數,所以被成為「虛」函數。

  虛函數只能藉助於指針或者引用來達到多態的效果,如果是下面這樣的代碼,則雖然是虛函數,但它不是多態的:

class A
{
public:
virtual void foo();
};

class B: public A
{
virtual void foo();
};

void bar()
{
A a;
a.foo(); // A::foo()被調用
}



1.1 多態
  在了解了虛函數的意思之後,再考慮什麼是多態就很容易了。仍然針對上面的類層次,但是使用的方法變的複雜了一些:

void bar(A * a)
{
a->foo(); // 被調用的是A::foo() 還是B::foo()?
}


  因為foo()是個虛函數,所以在bar這個函數中,只根據這段代碼,無從確定這裡被調用的是A::foo()還是B::foo(),但是可以肯定的說:如果a指向的是A類的實例,則A::foo()被調用,如果a指向的是B類的實例,則B::foo()被調用。

  這種同一代碼可以產生不同效果的特點,被稱為「多態」。

1.2 多態有什麼用?
  多態這麼神奇,但是能用來做什麼呢?這個命題我難以用一兩句話概括,一般的C++教程(或者其它面向對象語言的教程)都用一個畫圖的例子來展示多態的用途,我就不再重複這個例子了,如果你不知道這個例子,隨便找本書應該都有介紹。我試圖從一個抽象的角度描述一下,回頭再結合那個畫圖的例子,也許你就更容易理解。

  在面向對象的編程中,首先會針對數據進行抽象(確定基類)和繼承(確定派生類),構成類層次。這個類層次的使用者在使用它們的時候,如果仍然在需要基類的時候寫針對基類的代碼,在需要派生類的時候寫針對派生類的代碼,就等於類層次完全暴露在使用者面前。如果這個類層次有任何的改變(增加了新類),都需要使用者「知道」(針對新類寫代碼)。這樣就增加了類層次與其使用者之間的耦合,有人把這種情況列為程序中的「bad smell」之一。

  多態可以使程式設計師脫離這種窘境。再回頭看看1.1中的例子,bar()作為A-B這個類層次的使用者,它並不知道這個類層次中有多少個類,每個類都叫什麼,但是一樣可以很好的工作,當有一個C類從A類派生出來後,bar()也不需要「知道」(修改)。這完全歸功於多態--編譯器針對虛函數產生了可以在運行時刻確定被調用函數的代碼。

鍵盤也能翻頁,試試「← →」鍵

302 Found

302 Found

The requested resource resides temporarily under a different URI.


Powered by Tengine

相關焦點

  • c++ 內存,虛函數,運算函數,三角函數
    :就是java中的抽象,純虛函數只有聲明沒有具體實現就是空方法,在子類中必須重新寫,虛函數就是在基類中寫了有實現。他們都得用關鍵字 virtual(虛擬的) 聲明的函數1. 虛函數和純虛函數可以定義在同一個類(class)中,含有純虛函數的類被稱為抽象類(abstract class),而只含有虛函數的類(class)不能被稱為抽象類(abstract class)。2.
  • 一個簡單的「貓吃老鼠」例子,5分鐘徹底弄懂C++中的虛函數
    初學者剛接觸C++語言中的 virtual 函數(虛函數)時,常常會感覺到迷惑,比如,書上說虛函數定義在基類中,其他繼承此基類的派生類都可以重寫該虛函數,因此虛函數是C++語言多態特性中非常重要的概念。但是派生類也可以重寫基類中的其他的常規函數(非虛函數)呀,那為什麼還要引入虛函數這樣看起來很複雜的概念呢?
  • C++的轉換手段並與explicit關鍵詞配合使用
    ++作者:良知猶存轉載授權以及圍觀:歡迎添加微信公眾號:羽林君隱式轉化c++語言不會直接將兩個不同類型的值相加,二十先根據類型轉化規則設法將運算對象的類型統一後再求值。例如 int value = 3.14 +3;這個程序是可以編譯通過的,只不過編譯器可能會警告改運算損失了精度。
  • VBA中的FUNCTION(函數)
    Excel用戶對「函數」這個詞一定不會陌生,Excel中大約有200個內置函數,我們常見的Excel函數有求和函數SUM()、條件函數IF()、查找函數VLOOKUP()等。
  • c++ 槽函數專題及常見問題 - CSDN
    它是一種函數回調機制,當一個信號關聯了多個槽時,信號發出,這些槽將會被調用,當然,也可以僅僅關聯一個槽函數。第一個模板參數Signature的含義和function相同,也是一個函數類型,表示signal調用的函數(槽,事件處理handler),例如:signal<void(int, double)> sig
  • C++後端開發面試題與知識點匯總(附答案)
    以下匯總C++後臺開發面試題與知識點,還有其他崗位的相關題庫和資料,想要什麼崗位的可以留言哦~附面試題目:一、基礎知識1、基本語言說一下C++和C的區別說一下C++中static關鍵字的作用說一說c++中四種cast轉換請說一下C/C++ 中指針和引用的區別?
  • C++開發必看 四種強制類型轉換的總結
    必須要有虛函數。  3. 相同基類不同子類之間的交叉轉換。但結果是NULL。class BaseClass { public: int m_iNum; virtual void foo(){}; //基類必須有虛函數。
  • 過程(Sub)、函數(Function)、集合(Collection)的作用範圍
    大家好,今天繼續講解類和類模塊應用,今日講解第3講內容:過程(Sub)、函數(Function)、集合(Collection)對象的作用範圍域。一過程(Sub)、函數(Function)也有作用範圍(或者叫作用域)。
  • C++中函數重載的例子
    函數重載是指在同一作用域內,可以有一組具有相同函數名,不同參數列表的函數,這組函數被稱為重載函數。重載函數通常用來命名一組功能相似的函數,這樣做減少了函數名的數量,避免了名字空間的汙染,對於程序的可讀性有很大的好處。
  • Implicit Function微分詳解
    Implicit function
  • 高階函數不會用?教你JS中最實用的幾個高階函數用法
    其實從閉包的例子中我們就已經看到了關於高階函數的相關內容了,哈哈還記得在我們去判斷數據類型的時候,我們都是通過Object.prototype.toString來計算的。每個數據類型之間只是'[object XXX]'不一樣罷了。所以在我們寫類型判斷的時候,一般都是將參數傳入函數中,這裡我簡單寫一下實現,咱們先來看看。
  • 特殊函數I:Bessel函數簡介(一)
    但是利用級數,我們能夠得到這種函數的一個比較易於觀看和分析的形式,亦即此種函數的非初等表達。因為具體地考慮到級數形式中的作為單獨通項的函數的形式的簡潔性,所以事實上,在數值分析和物理學等一些科學的研究中,使用函數的級數形式甚至比原函數本身都更加普遍。
  • 零基礎java入門教程函數function實例化格式案例void返回值說明
    java基礎自學入門:函數:定義在類中的具有特定功能的一段獨立小程序有時候我們函數也稱為方法,平時我們聽到的函數也就是方法,方法也是函數,每個人的叫法不同,所以這裡要切記。老程式設計師別露餡喲。哈哈哈哈函數的英文單詞function這個一定要認識下面實例化下函數的格式:修飾符 返回值類型 函數名(參數類型 形參1,參數類型 形參2, ……){
  • 論文精選|磨削表面粗糙度預測的BPNN模型激活函數選擇方法
    This paper proposes an activation function selection approach in which virtual data generated from the approximate physical model are employed to evaluate the performance of the BPNN in practice application
  • Google軟體工程師解讀:深度學習的activation function哪家強?
    正是由於這些非線性函數的反覆疊加,才使得神經網絡有足夠的capacity來抓取複雜的pattern,在各個領域取得state-of-the-art的結果。顯而易見,activation function在深度學習中舉足輕重,也是很活躍的研究領域之一。目前來講,選擇怎樣的activation function不在於它能否模擬真正的神經元,而在於能否便於優化整個深度神經網絡。
  • 基於Matlab和Visual C++的數字濾波器設計方法
    在信號處理系統中,輸入信號通常含有各種噪聲和幹擾。為對信號進行準確的測量和控制,必須削弱或濾除被測信號中的噪聲和幹擾。一般在系統中可選用硬體濾波和軟體濾波。硬體濾波又分為無源濾波和有源濾波,無源濾波是通過RC濾波器或LC濾波器等模擬濾波器進行濾波。軟體濾波也稱數字濾波,是通過一定的算法削弱噪聲的影響。硬體濾波的優勢是不需要進行複雜的程序處理,反應靈敏。
  • php中函數禁用繞過的原理與利用
    bypass disable function蟻劍項目倉庫中有一個各種disable的測試環境可以復現,需要環境的師傅可以選用蟻劍的環境。看幾種常見用於執行系統命令的函數:system,passthru,exec,pcntl_exec,shell_exec,popen,proc_open,``當然了這些也常常出現在disable function中,那麼可以尋找可以比較容易被忽略的函數,通過函數 or 函數組合拳來執行命令。
  • 貫穿C++ 11 與 C++ 17 的 Lambda 到底是個什麼?
    作者 | Vishal Chovatiya譯者 | 蘇本如,責編 | maozz以下為譯文:Lambda函數是C++ 11中引入的現代C++的一個直觀概念,因此在網際網路上可以找到大量的關於Lambda函數的文章。
  • 【C++】C++獲取系統日期時間
    獲取日期C語言中讀取系統時間的函數為time(),其函數原型為:#include <time.h>time_t time( time_t * ) ;time_t就是long,函數返回從1970年1月1日(MFC是1899年12月31