虚拟功能的重载

Yam*_*mar 8 c++ inheritance overriding 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;
}
Run Code Online (Sandbox Code Playgroud)

上面代码的输出是:

Base::fun(), x = 0
Derived::fun(), x = 10
Derived::fun(), x = 1.2
Run Code Online (Sandbox Code Playgroud)

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

void fun(int x = 0)
void fun(float x = 10.0)
Run Code Online (Sandbox Code Playgroud)

这些功能不可能过载.

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

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

tem*_*def 15

在C++中,对于覆盖基类函数的成员函数,参数类型必须与基类函数的参数类型完全匹配.由于基类函数接受a int并且派生类的函数接受a 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;
    }
};
Run Code Online (Sandbox Code Playgroud)

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

Derived d1;
Base *bp = &d1;
bp->fun();
Run Code Online (Sandbox Code Playgroud)

这里,由于该行bp->fun()使用基类指针调用,C++ Base会查看要调用的函数.它找到了Base::fun(int).现在,由于该功能已被标记virtual,它将调用,Base::fun(int)除非有什么东西覆盖它.但由于没有覆盖,Base::fun(int)最终会被调用.

那么后来这两行呢?

d1.fun();
d1.fun(1.2);
Run Code Online (Sandbox Code Playgroud)

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

所以,总结一下:

  • 你引入了一个重载,而不是重写.使用override关键字可以帮助您将来诊断此类问题.
  • fun通过基指针调用会查找名为funtake in的函数int,因为基指针的fun函数接受了int.找到版本,Base因为没有oerride.
  • 调用fun派生对象会查找名为funstart in 的函数Derived,并找到您的覆盖.