2015-04-04 68 views
1

爲什麼如果基類函數在派生類中被重載,則該函數的基類版本(即使是public)不能通過派生類的對象訪問?在派生類中重載基類函數

如:

#include <iostream> 
#include <string> 

using namespace std; 

class Base { 
public: 
    void f(int i) { 
     cout << "\nInteger: " << i << endl; 
    } 
}; 

class Derived : public Base { 
public: 
    void f(string s) { 
     cout << "\nString: " << s << endl; 
    } 
}; 


int main() { 
    Base b; 
    Derived d; 
    //d.f(5); Doesn't work 
    d.f("Hello"); 
    //d.Base::f(5); works though 
    return 0; 
} 
+0

[這](http://stackoverflow.com/questions/2391679/why-do-we-need-virtual-methods-in-c)可能有關係 – wowofbob 2015-04-04 21:23:52

回答

1

名稱查找,重載決議之前進行。名稱查找在一個範圍內開始,如果它沒有找到該名稱的聲明,它將搜索一個封閉範圍,依此類推,直到找到該名稱。在這種情況下,d.f找到聲明void Derived::f(string)。只有在Derived中沒有聲明f成員的名稱查找纔會繼續搜索基類。只有在找到名稱後,編譯器纔會確定是否存在適當的過載,如果是,那麼哪個過載是最匹配的。

注意,您可以重新聲明的基類函數在派生類中,以迫使它發現:

class Derived : public Base { 
public: 
    using Base::f; 
    void f(string s) { 
     cout << "\nString: " << s << endl; 
    } 
}; 

現在的名稱查找會發現f既重載然後重載決議將決定哪一個呼叫。

0

如果你希望能夠在除了Derived::fBase::f,您可以在Derived添加一行

using B::f; 

class Derived : public Base { 
    public: 
     using Base::f; 
     void f(string s) { 
     cout << "\nString: " << s << endl; 
     } 
}; 

現在你可以使用:

Derived d; 
d.f(10); 
d.f("Hello");