考虑这个演示程序:
#include <stdio.h>
class Base
{
public:
virtual int f(int) =0;
virtual int f(){ return f(0); }
virtual ~Base(){ }
};
class Derived : public Base
{
public:
int f(int i)
{
return (10 + i);
}
};
int main(void)
{
Derived obj;
printf("%d\n", obj.f(1)); // This works, and returns 11
printf("%d\n", obj.f()); // Adding this line gives me the error listed below
}
这给了我以下编译错误:
virtualfunc.cpp: In function ‘int main()’:
virtualfunc.cpp:25:26: error: no matching function for call to ‘Derived::f()’
virtualfunc.cpp:15:9: note: candidate is: virtual int Derived::f(int)
我希望调用obj.f()
会导致调用Base::obj.f()
,因为派生类没有定义它,这会导致调用Derived::obj.f(0)
每个类Base中的定义。
我在这里做错了什么?有没有办法实现这个目标?具体来说,我希望调用obj.f()
返回10。
(另请注意,我意识到我可以使用默认参数来解决此问题,但此代码只是我问题的简明示例,所以请不要告诉我使用默认参数。)
感谢。
答案 0 :(得分:8)
您遇到的问题与纯虚函数正交,与C ++在类层次结构中的名称解析有关。
写作时
obj.f();
C ++尝试查找名为f
的函数,以便它知道要调用的内容。由于obj
的类型为Derived
,因此它会从Derived
内部开始,并查找名为f
的函数。它最终找到Derived::f(int)
,即使这个函数接受了一个参数,C ++认为这是你试图调用的方法,因此停止查找。然后编译器注意到你试图在没有参数的情况下调用它,给你关于函数调用的错误。
要解决此问题,您需要告诉C ++编译器它还需要尝试查找基类中包含的函数Base::f()
。为此,您可以按如下方式更改Derived
的定义:
class Derived : public Base
{
public:
int f(int i)
{
return (10 + i);
}
using Base::f;
};
这一行using Base::f
告诉C ++它应该将名为Base
的{{1}}中的函数视为f
的一部分。这样,当编译器尝试查找名为Derived
的函数时,它会同时找到f
和Derived::f(int)
。然后调用将成功,因为编译器可以确定您尝试使用您列出的代码调用Base::f()
。
希望这有帮助!
答案 1 :(得分:3)
派生类中f(int)
的定义隐藏了您未覆盖的Base::f
名称。您需要做的就是通过在派生类中编写using Base::f;
来取消隐藏:
class Derived : public Base
{
public:
using Base::f; //note this line!
int f(int i)
{
return (10 + i);
}
};
答案 2 :(得分:3)
原因是,f
类中定义的Derived
(hides
)f
Base
函数。解决方案是添加using
。像这样:
class Derived : public Base
{
public:
int f(int i)
{
return (10 + i);
}
// vvvvvvvvvvvvvv
using Base::f;
};