这不起作用:
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 :(得分:5)
本质上,名称查找在重载解析之前发生,因此派生类中的函数A
会覆盖基类中的虚函数,但会隐藏任何基类中具有相同名称的所有其他函数。
可能的解决方案包括在派生类中添加using Foo::A;
指令,以使派生类中可见的所有基类成员A
可见,或者对具有不同签名的函数使用不同的名称。
同样请参阅here。
答案 1 :(得分:2)
这里有一个讨论:http://bojolais.livejournal.com/222428.html
关键是:在C ++中,当你有一个带有重载方法的类(成员函数,你想要调用它)时,然后扩展并覆盖该方法,你必须覆盖所有重载的方法
解决方法是将呼叫更改为:
b.Foo::A(0, 0);
答案 2 :(得分: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)
}
答案 3 :(得分:0)
最简单的思考方法是记住,重载总是在单个范围内发生,而覆盖范围之间会出现重写。在确定要调用哪个函数时,编译器FIRST会查找具有该名称的最近作用域,然后解析该作用域中定义之间的重载。
答案 4 :(得分:0)
要添加上述回复,
你也可以在Bar的范围内定义重载函数,如果这是预期的结果,它总是在Foo的范围内调用相同的函数。这样可以更容易地看到代码按预期运行。