2015-04-04 70 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");