覆盖非虚拟方法


81

让我们在Visual C ++ 2010中假设这种情况:

#include <iostream>
#include <conio.h>

using namespace std;

class Base
{
public:
    int b;
    void Display()
    {
        cout<<"Base: Non-virtual display."<<endl;
    };
    virtual void vDisplay()
    {
        cout<<"Base: Virtual display."<<endl;
    };
};

class Derived : public Base
{
public:
    int d;
    void Display()
    {
        cout<<"Derived: Non-virtual display."<<endl;
    };
    virtual void vDisplay()
    {
        cout<<"Derived: Virtual display."<<endl;
    };
};

int main()
{
    Base ba;
    Derived de;

    ba.Display();
    ba.vDisplay();
    de.Display();
    de.vDisplay();

    _getch();
    return 0;
};

从理论上讲,此小应用程序的输出应为:

  • 基本:非虚拟显示。
  • 基本:虚拟显示。
  • 基本:非虚拟显示。
  • 派生:虚拟显示。

因为Base类的Display方法不是虚拟方法,所以Derived类不应覆盖它。对?

问题是,当我运行该应用程序时,它显示以下内容:

  • 基本:非虚拟显示。
  • 基本:虚拟显示。
  • 派生:非虚拟显示。
  • 派生:虚拟显示。

因此,要么我不了解虚拟方法的概念,要么在Visual C ++中发生一些奇怪的事情。

有人可以帮我一个解释吗?


您将绝对拥有Base:非虚拟展示。在将行更改为时de.Base::Display()
v.oddou

Answers:


122

是的,你有点误会。

在这种情况下,派生类上同名的方法将隐藏父方法。您会想到,如果不是这种情况,尝试创建与基类非虚拟方法同名的方法将引发错误。它是允许的,这不是问题-如果您直接完成该方法,则将其命名为罚款。

但是,由于是非虚拟的,因此不会使用允许多态的C ++方法查找机制。因此,例如,如果您创建了派生类的实例,但通过指向基类的指针调用了“ Display”方法,则将调用基类的方法,而对于“ vDisplay”,将调用派生方法。

例如,尝试添加以下行:

Base *b = &ba;
b->Display();
b->vDisplay();
b = &de;
b->Display();
b->vDisplay();

...并按预期观察输出:

基本:非虚拟显示。
基本:虚拟显示。
基本:非虚拟显示。
派生:虚拟显示。


您好@ sje397,谢谢您的答复。您能否编写一个如您所说的通过指向基类的指针来调用方法的示例?谢谢!
Leif Lazar

就像我说的那样,您还可以使用范围解析语法从派生实例中调用(非虚拟)基本方法。
v.oddou

因此,可以肯定的是,无论是否将其声明为虚拟方法,我都可以在基类中定义一个方法,并在派生类中重写它。唯一的区别是,如果基指针指向派生类对象,则调用该方法将对基类的方法(如果它不是虚拟的)进行校准,而对派生类的方法(如果它是虚拟的)进行校准。那正确吗?还有其他区别吗?
SexyBeast

@Cupidvogel是的,这是正确的。声明为“虚拟”意味着C ++将使用支持多态的机制,并在您通过基类指针进行调用时检查该方法是否有更多派生版本。我想不出其他任何区别。
sje397

仅更改头文件是否足够?还是必须使用“虚拟”关键字来编译源?
Paul Knopf

13

是的,您有点误解了:

纯虚函数:

virtual void fun1()=0 ->必须在派生类中重写

虚函数:

virtual void fun2() ->可以被覆盖

正常功能:

void fun3() ->不要覆盖它

为了实现运行时多态,您需要重写c ++中的虚函数


5

我认为在静态绑定与动态绑定的上下文中查看它也可能更好。

如果该方法是非虚拟的(与Java不同,C ++中已默认使用该方法),则该方法在编译时绑定到其调用者,这是不可能知道将在运行时指向的实际对象的。因此,变量类型是所有重要的基础。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.