C++纯虚方法

5

考虑这个演示程序:

#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(),因为派生类没有定义它,这样将按照类Base中的定义导致调用Derived::obj.f(0)。请问我做错了什么?有什么办法可以解决这个问题吗?具体来说,我希望调用obj.f()返回10。(还请注意,我知道可以使用默认参数来解决这个问题,但是这段代码仅仅是我遇到的问题的简明示例,请不要告诉我使用默认参数。)谢谢。

1
Derived 中的 f 函数“隐藏”了在 Base 中定义的其他函数。这就是为令你出现此错误的原因。 - Kiril Kirov
2
请仅返回翻译后的文本:C++成员函数可以同时使用virtual、override和overload吗? - parapura rajkumar
1
@Kiril Kirov,你赢了——如果你想回答这个问题,我会将其标记为正确。在派生类定义中明确添加using Base::f;解决了它。谢谢! - jedwards
@raj -- 是的,看起来是这样的;我很抱歉。实际上,我浏览了大约20个左右的问题,都没有回答我的问题,也没有看到这个问题。 - jedwards
@jedwards - 我很高兴能够帮到你。我添加了我的回答 (: - Kiril Kirov
显示剩余2条评论
3个回答

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++ 应该把名为 fBase 中的函数看作是 Derived 的一部分。这样,当编译器查找名为 f 的函数时,它会找到 Derived::f(int)Base::f() 两个函数。调用将成功,因为编译器可以确定你试图使用你列出的代码调用 Base::f()
希望这有所帮助!

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);
    }
};

@Mahesh:这与虚拟机制无关,因为他正在使用派生类型的对象。 - Nawaz
我在这里没有看到任何虚拟的特定用法。 - Mahesh

3
原因是,在Derived中定义的f函数会隐藏来自Base类的f函数。解决方法是添加using。像这样:
class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }

//  vvvvvvvvvvvvvv
    using Base::f;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接