2010-07-05 67 views
4

类请看下面的代码:成员函数隐藏在派生

#include <iostream> 
using namespace std; 

class A { 
    public: 
    A() {};  
    virtual void foo(double d) { cout << d << endl; } 
    virtual void foo(double d, int a) = 0; 
    }; 

class B : public A { 
    public: 
    B() {}; 
    virtual void foo(double d, int a) { cout << d << endl << a << endl; } 
    }; 

int main() 
    { 
    B b; 
    b.foo(3.14); 
    return 0; 
    } 

编译器(试过G ++和Visual C++ 2008)说,有没有像B无功能:FOO(双)。 G ++的确切消息是:

main.cpp:21: error: no matching function for call to ‘B::foo(double)’

它看起来像hiding rule的效果,但在我看来,规则不应该用在这里,因为我不重写富(双)和两个FOO方法定义在基类中。

我知道我可以在派生类B.

你能解释一下为什么代码不编译和C的哪些规则++适用于这里与

using A::foo; 

声明解决这一问题?

+1

这只是“名称隐藏”问题。为什么你不能只使用'使用A :: foo'子句? – ereOn 2010-07-05 07:56:04

+0

不是一个确切的重复,但在这里讨论相同的问题:http://stackoverflow.com/questions/72010/c-overload-resolution – ereOn 2010-07-05 08:00:12

+0

在这种情况下,如果你想实现你的纯虚拟富方法你必须重新定义所有的方法名称“foo”或为纯虚拟方法和实施方法选择不同的名称。 – Sergey 2010-07-05 08:56:36

回答

4

隐藏规则不是重写,而是隐藏名称。如果派生类声明了一个成员函数,则会隐藏具有相同名称的其他基类成员函数。这也发生在你的情况。

1

对我来说看起来完全合理。虽然函数签名对于知道函数是什么很重要,但我可以看到这种行为如何防止非常愚蠢的错误。

正如ereOn建议的那样,使用指令是一个公平的支付价格。

+0

+1:如果你想了解更多,你可以看看http://becomeaprogrammerin21years.blogspot.com/2008/03/c-inheritance-oddity.html – ereOn 2010-07-05 08:02:12

5

名称阴影,而不是特定的功能。一旦在B中制作foo,则所有基本foo(注意,按名称!)都会被遮蔽。

2

当编译器遇到一个标识符时,查找规则就会启动并开始搜索该标识符。在具体情况下,编译器知道foo必须是B或其子类之一的成员。查找规则指出,编译器必须从大多数派生类(考虑对象的静态类型)开始并在层次结构中进行跟踪,一旦在一个级别中找到标识符,将只考虑该级别的定义,不能继续向上看。不管什么f回报

B& f(); // might return a B or something derived from B 
void test() { 
    B& b = f(); // static type is B 
    b.foo(1.0); 
} 

,静态类型是B,所以编译器将在B类查找和发现B::foo(double,int)。由于该级别没有其他foo声明,因此编译器必须尝试将函数调用与可用的方法声明进行匹配(并使其失败)。

重要的是,查找不看对象,而是看起来按类型和向上,只要遇到第一个实例切割。