2011-03-21 101 views
4
#include <iostream> 
class base 
{ 
    public: 
    virtual void print (int a) 
    { 
     std::cout << "a: " << a << " base\n"; 
    } 
    virtual void print (int a, int b) 
    { 
     std::cout << "base\n"; 
    } 
}; 

class derived : public base 
{ 
    public: 
    virtual void print (double d) 
    { 
     std::cout << "derived\n"; 
    } 
}; 

int main() 
{ 
    int i = 10; 
    double d = 10000.0; 
    base *b = new derived(); 
    b->print (i, i); 
    b->print (d); 

    return 0; 
} 

這個函數的輸出是:什麼是虛函數查找規則?

base 
a: 10000 base 
  • 爲什麼b->print (d)不調用派生類的實現和 執行對'd'靜態澆鑄爲用戶提供基類 實現匹配?
  • 什麼規則是虛函數查找在這裏應用?
+3

您正在使用類型庫,而不是派生。它沒有一個函數需要一個double,所以它將轉換爲int來找到最佳匹配。 – Rob 2011-03-21 00:33:56

回答

8

derived::print不覆蓋base中的任何成員函數。它被聲明爲具有double類型的單個參數,但命名爲baseprint兩個虛擬成員函數被聲明爲具有int類型的一個和兩個參數。

當您使用b->print(d),只有在base成員函數重載解析過程中考慮,所以只有void base::print(int)void base::print(int, int)被考慮。 void derived::print(double)無法找到,因爲編譯器不知道b指向derived對象。

如果derived要覆蓋在base中聲明爲虛擬成員函數的兩個print函數中的一個,則該覆蓋將在運行時調用。

(在一定程度上相關的說明,derived::print隱藏兩個base::print成員函數,所以如果你要嘗試使用的基類print功能之一,例如,derived().print(1, 1),它會失敗,你需要使用一個使用聲明使名稱查找過程中可用的那些成員函數。)

0

由於雙可以在它看到的第一個定義自動地轉換爲int(在基類)

參見explicit關鍵字或this question

1

重載解析發生在編譯時。覆蓋在運行時發生。

因此,​​的重載分辨率首先發生。這將選擇Base::print(int),因爲它是唯一一個參數print

在運行時,b指向Derived對象,該對象沒有覆蓋Base::print(int)。因此,Base::print(int)仍稱。