程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 虛函數的訪問控制與多態

虛函數的訪問控制與多態

編輯:C++入門知識

虛函數的訪問控制與多態


這裡文章的題目是自擬的,只因為自己發現虛函數的訪問控制,與自己之前的理解有出入,於是備忘之。

首先,虛函數是實現多態的機制,也就是說在利用基類的指針或者引用調用虛函數時,調用的是該指針或者引用的動態類型的相應的函數,這裡有幾點需要備忘的。

1 編譯器在決定調用函數時,如果該函數是虛函數才會在運行時確定調用什麼函數,如果不是虛函數,那麼在編譯階段就已經確定了調用的函數類型,如下面的代碼;

基類與派生類都聲明了函數f。但是在main函數的調用中編譯器調用的是靜態類型對應的函數,因為f函數並不是虛函數,雖然在基類與派生類中都聲明了該函數。

這是顯然的,沒有虛函數,就沒有多態了,也就無所謂動態類型了。函數的所有調用都是靜態綁定。


2 基類定義虛函數為public,派生類覆蓋了該虛函數,但是將其聲明為private,這樣當基類的指針綁定到派生類的對象時,使用該基類指針調用該虛函數時,調用是否成功。如果二者的訪問權限反過來呢。

class Base
{
public:
    virtual void f(int i=0) {cout << "f() in Base..." << i << endl;}
};
class Derived:public Base
{
private:
    void f(int i=1){cout << "f() in derived..." << i << endl;}
};

int main(void)
{
    Base *b = new Derived();
    b->f();
    return 0;
}

上述代碼的輸出為: f() in derived 0

首先分析,為什麼輸出結果是f() in derived. 編譯器在看到b對f進行調用時,此時編譯器根據b的靜態類型(也就是Base)來決定f函數是否可訪問,由於f函數式public的,OK, "訪問控制為public"並沒有影響調用,並且進行形參的默認參數的賦值。

由於f是虛函數,那麼具體調用哪個函數是在運行時確定的,於是,在運行時查找Derived的虛函數表,得到虛函數f(此時的f已經被Derived類覆蓋,於是調用的就是派生類的版本。)

至於,為什麼i的值為0,上述分析也已經說明了,也可以參見文章 點擊打開鏈接

如果將兩者的訪問權限交換,那麼訪問控制這一關都過不了,其實很簡單,既然你需要派生類繼承f函數,將其在Base類中聲明為private本身就是不對的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved