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)

我希望调用 toobj.f()会导致调用,Base::obj.f()因为派生类没有定义它,然后会导致调用Derived::obj.f(0)每个类 Base 中的定义。

我在这里做错了什么?有没有办法做到这一点?具体来说,我希望调用obj.f()返回 10。

(另外请注意,我意识到我可以使用默认参数来解决这个问题,但这段代码只是我的问题的一个简明示例,所以请不要告诉我使用默认参数。)

谢谢。

4

3 回答 3

8

您遇到的问题与纯虚函数正交,并且与 C++ 如何在类层次结构中进行名称解析有关。

当你写

obj.f();

C++ 试图寻找一个名为的函数f,以便它知道要调用什么。由于objis 的类型Derived,它从内部开始Derived并寻找一个名为 的函数f。它最终 find 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++ 它应该将Basenamed中的函数f视为Derived. 这样,当编译器尝试查找名为 的函数时f,它会同时找到Derived::f(int)Base::f()。然后调用将成功,因为编译器可以确定您正在尝试Base::f()使用您列出的代码进行调用。

希望这可以帮助!

于 2011-06-03T22:07:12.327 回答
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);
    }
};
于 2011-06-03T22:08:20.377 回答
3

原因是,定义了f(in Derived)类中hidesf函数Base。解决方案是添加using. 像这样:

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }

//  vvvvvvvvvvvvvv
    using Base::f;
};
于 2011-06-03T22:09:42.697 回答