隐藏在派生类中的成员函数

时间:2010-07-05 07:53:48

标签: c++

请查看以下代码:

#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(double)这样的函数。 g ++的确切消息是:

  

main.cpp:21:错误:没有匹配函数来调用'B :: foo(double)'

它看起来像hiding rule的效果,但在我看来,规则不应该在这里使用,因为我没有覆盖foo(double),并且两个foo方法都在基类中定义。

我知道我可以用

解决问题
using A::foo;
派生类B中的

声明。

你能解释为什么代码不能编译以及C ++的规则适用于何处?

4 个答案:

答案 0 :(得分:5)

命名阴影,而不是特定功能。在foo中创建B之后,所有基础foo(注意,名称!)都会被遮蔽。

答案 1 :(得分:4)

隐藏规则不是覆盖,而是隐藏名称。如果派生类声明了成员函数,则会隐藏具有相同名称的其他基类成员函数。在您的情况下也会发生这种情况。

答案 2 :(得分:2)

当编译器遇到标识符时,查找规则启动并开始搜索该标识符。在具体情况下,使用b.foo,编译器知道foo必须是B或其子类之一的成员。查找规则声明编译器必须从最派生类开始(考虑对象的静态类型)并在层次结构中跟进,并且一旦在一个级别中找到标识符,则仅考虑该级别中的定义,一定不要一直向上看。

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

无论f返回什么,静态类型都是B,因此编译器将在B类中查找并找到B::foo(double,int)。由于该级别没有其他foo声明,因此编译器必须尝试使用​​可用的方法声明来匹配(和失败)函数调用。

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

答案 3 :(得分:1)

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

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