重写非虚方法

让我们在 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 方法不是虚方法,所以派生类不能重写它。对吧?

问题在于,当我运行应用程序时,它会打印以下内容:

  • 基础: 非虚拟显示。
  • 基地: 虚拟显示。
  • 派生: 非虚拟显示。
  • 派生: 虚拟显示。

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

有人能给我解释一下吗?

96172 次浏览

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.

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.

Yes you have misunderstood a little:

Pure virtual functions:

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

Virtual functions:

virtual void fun2() -> can be overridden

Normal functions:

void fun3() -> don't override it

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

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'.