C++ 覆盖非虚方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11067975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:48:06  来源:igfitidea点击:

Overriding non-virtual methods

c++overriding

提问by Leif Lazar

Let's assume this scenario in Visual C++ 2010:

让我们在 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;
};

Theoretically, the output of this little application should be:

理论上,这个小应用程序的输出应该是:

  • Base: Non-virtual display.
  • Base: Virtual display.
  • Base: Non-virtual display.
  • Derived: Virtual display.
  • 基础:非虚拟显示器。
  • 基础:虚拟显示。
  • 基础:非虚拟显示器。
  • 衍生:虚拟显示。

because the Display method of the Base class is not a virtual method so the Derived class should not be able to override it. Right?

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

The problem is that when I run the application, it prints this:

问题是当我运行应用程序时,它会打印:

  • Base: Non-virtual display.
  • Base: Virtual display.
  • Derived: Non-virtual display.
  • Derived: Virtual display.
  • 基础:非虚拟显示器。
  • 基础:虚拟显示。
  • 衍生:非虚拟显示器。
  • 衍生:虚拟显示。

So either I didn't understand the concept of virtual methods or something strange happens in Visual C++.

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

Could someone help me with an explanation?

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

回答by sje397

Yep, you are misunderstanding a little.

是的,你有点误会了。

The method of the same name on the derived class will hide the parent method in this case. You would imagine that if this weren't the case, trying to create a method with the same name as a base class non-virtual method should throw an error. It is allowed and it's not a problem - and if you call the method directly as you have done it will be called fine.

在这种情况下,派生类上的同名方法将隐藏父方法。您可能会想象,如果不是这种情况,尝试创建一个与基类非虚拟方法同名的方法应该会引发错误。这是允许的,这不是问题 - 如果你像你所做的那样直接调用该方法,它将被很好地调用。

But, being non-virtual, C++ method lookup mechanisms that allow for polymorphism won't be used. So for example if you created an instance of your derived class but called your 'Display' method via a pointer to the base class, the base's method will be called, whereas for 'vDisplay' the derived method would be called.

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

For example, try adding these lines:

例如,尝试添加这些行:

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

...and observe the output as expected:

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

Base: Non-virtual display.
Base: Virtual display.
Base: Non-virtual display.
Derived: Virtual display.

基础:非虚拟显示器。
基础:虚拟显示。
基础:非虚拟显示器。
衍生:虚拟显示。

回答by Avinash Aitha

Yes you have misunderstood a little:

是的,你有点误解了:

Pure virtual functions:

纯虚函数:

virtual void fun1()=0-> must be overridden in the derived class

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

Virtual functions:

虚拟功能:

virtual void fun2()-> can be overridden

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

Normal functions:

正常功能:

void fun3()-> don't override it

void fun3()-> 不要覆盖它

In order to achieve runtime polymorphism you need to override virtual functions in c++

为了实现运行时多态性,您需要覆盖 C++ 中的虚函数

回答by stdout

I think it might be also better to look at it in the context of static vs dynamic binding.

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

If the method is non-virtual (it's already by default in C++ unlike Java), then the method binds to it's caller at compile time which is impossible to know the actual object that will be pointed at runtime. So, variable type is all that matters which is the 'Base'.

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