虚拟功能的重载

时间:2017-03-15 17:33:40

标签: c++ inheritance override overloading

我在接受采访时被问到这个问题。我无法在那里回答这个问题。我现在也无法得到它,为什么输出是这样的。 这是代码:

#include <iostream>
using namespace std;

class Base
{
public:
    virtual void fun ( int x = 0)
    {
        cout << "Base::fun(), x = " << x << endl;
    }
};

class Derived : public Base
{
public:
    virtual void fun ( float x = 10.0 )
    {
        cout << "Derived::fun(), x = " << x << endl;
    }
};


int main()
{
    Derived d1;
    Base *bp = &d1;
    bp->fun();
    d1.fun();
    d1.fun(1.2);
    return 0;
}

上述代码的输出是:

Base::fun(), x = 0
Derived::fun(), x = 10
Derived::fun(), x = 1.2

问题是: 在第一种情况下,我们说fun()函数都被重载(并且因为它们的声明不同而没有被覆盖)并且调用了基本的fun(),但是这些fun()的声明不可能被重载(因为它们只是声明是否包含默认参数)

void fun(int x = 0)
void fun(float x = 10.0)

这些功能无法过载。

上述两种情况似乎都存在矛盾。

任何解释这种情况的相关文章/链接都会非常有用。

1 个答案:

答案 0 :(得分:13)

在C ++中,对于覆盖基类函数的成员函数,参数类型必须与基类函数的参数类型完全匹配。由于基类函数接受int并且派生类的函数接受float,因此它不被视为覆盖。您可以使用override关键字

来查看此内容
class Base
{
public:
    virtual void fun ( int x = 0)
    {
        cout << "Base::fun(), x = " << x << endl;
    }
};

class Derived : public Base
{
public:
    virtual void fun ( float x = 10.0 ) override // Doesn't compile!
    {
        cout << "Derived::fun(), x = " << x << endl;
    }
};

您的代码中发生的事情是C ++将您的函数视为重载(具有相同名称的另一个函数)而不是覆盖。我们来看看这段代码:

Derived d1;
Base *bp = &d1;
bp->fun();

这里,由于行bp->fun()使用基类指针调用,C ++会查找Base以查看要调用的函数。它找到了Base::fun(int)。现在,由于该功能已标记为virtual,因此除非有异常覆盖,否则会调用Base::fun(int)。但由于没有覆盖,Base::fun(int)最终会被调用。

那么后来这两行呢?

d1.fun();
d1.fun(1.2);

这里,由于您在静态类型Derived的对象上调用这些函数,C ++会尝试在fun类中查找名为Derived的函数。它找到了你的新函数Derived::fun(float),并且由于C ++在类中进行名称查找的方式,它不会在基类中查找Base::fun(int)。因此,这两个调用都被视为对Derived::fun(float)的调用,因此没有关于在没有参数的情况下调用哪个函数的歧义。编译器甚至从未查看Base类型,因为没有必要。

所以,总结一下:

  • 您已经引入了重载,而不是覆盖。使用覆盖关键字可以帮助您在将来诊断此类问题。
  • 通过基指针调用fun会查找名为fun的函数,该函数会引入int,因为基指针的fun函数会接收int 。找到Base中的版本,因为没有oerride。
  • 通过派生对象调用funfun开始查找名为Derived的函数,并找到您的覆盖。