2009-09-26 21 views
4

这不起作用:这里用C++重载和重载是怎么回事?

class Foo 
{ 
public: 
    virtual int A(int); 
    virtual int A(int,int); 
}; 
class Bar : public Foo 
{ 
public: 
    virtual int A(int); 
}; 

Bar b; 
int main() 
{ 
    b.A(0,0); 
} 

看来,通过覆盖Foo::A(int)Bar::A(int)我莫名其妙地隐藏Foo::A(int,int)。如果我添加一个Bar::A(int,int)的东西的工作。

有没有人有链接到这里发生了什么好的描述?

+0

可能重复:http://stackoverflow.com/questions/411103/function-with-same-name-but-different-signature-in-derived-class –

回答

5

本质上,名称查找发生在重载解析之前,因此派生类中的函数A将覆盖基类中的虚函数,但会隐藏所有其他基类中具有相同名称的函数。

可能的解决方案包括将using Foo::A;指令添加到派生类中,以使所有基类成员在派生类中都可见或称为A,或者使用具有不同签名的函数使用不同名称。

另请参阅here

+0

很高兴让我的怀疑证实。你知道有关C++这个角落完整描述的链接吗? – BCS

+1

标准的3.3.7 [basic.scope.hiding]中描述了名称隐藏,名称查找是3.4 [basic.lookup]的全部内容,并且有超载和重载解析的整个章节(13 [over])。尽管如此,您的情况的基本规则正如我所描述的那样。 –

2

有在这儿有讨论:http://bojolais.livejournal.com/222428.html

的症结是:在C++中,当你有一个重载的方法(成员函数,无论你怎么称呼它)一类,然后您扩展和覆盖这种方法,必须重写所有的重载方法

一种解决方法是改变调用的:

b.Foo::A(0, 0); 
0

想着这个的最简单方法是要记住,永远超载发生在一个单一的范围内,同时overrid ing在范围之间出现。当找出要调用哪个函数时,编译器FIRST会查找最接近的具有该名称的作用域,然后解析该作用域中定义之间的重载。

0

要添加上述反应,

你也可以定义在酒吧的范围,它总是调用美孚的范围相同功能的重载函数,如果这是预期的结果。这可以更容易地看到代码按预期运行。

2
// I think this kind of approach is best to avoid this kind of problems. 

class Foo 
{ 
private: 
    virtual int A_impl(int);  // note the private declaration 
    virtual int A_impl(int,int); // of the actual implementation. 
           // clients have access through the 
           // non-virtual interface. 

public: 
    inline int A(int x) 
    {       // the non virtual interface will always be visible. 
     return A_impl(x);  // and consistent. 
    } 
    inline int A(int x, int y) 
    { 
     if (x != y) {   // also permits global parameter validation 
      return A_impl(x, y); // and it's easier to set breakpoints on a 
     }      // single entry point. 
     return 0; 
    } 
}; 
class Bar : public Foo 
{ 
private: 
    virtual int A_impl(int); 
}; 

Bar b; 
int main() 
{ 
    b.A(0,0);     // never again stuff like: ((A*)&b)->A(0,0) 
}