Overriding non-virtual methods
让我们假设Visual C++ 2010中的这个场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #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; }; |
理论上,这个小应用程序的输出应该是:
- 基本:非虚拟显示。
- 基础:虚拟显示。
- 基本:非虚拟显示。
- 派生:虚拟显示。
因为基类的显示方法不是虚拟方法,所以派生类不应该重写它。对吗?
问题是,当我运行应用程序时,它会打印以下内容:
- 基本:非虚拟显示。
- 基础:虚拟显示。
- 派生:非虚拟显示。
- 派生:虚拟显示。
所以我不理解虚拟方法的概念或者在VisualC++中发生了一些奇怪的事情。
有人能帮我解释一下吗?
是的,你有点误会。
在这种情况下,派生类上同名的方法将隐藏父方法。如果不是这样,尝试创建一个与基类同名的非虚拟方法会引发错误。它是允许的,这不是问题——如果像您所做的那样直接调用该方法,它将被称为fine。
但是,作为非虚的,不允许使用多态性的C++方法查找机制。因此,例如,如果创建了派生类的实例,但通过指向基类的指针调用了"display"方法,则将调用基的方法,而对于"vdisplay",则将调用派生方法。
例如,尝试添加这些行:
1 2 3 4 5 6 | Base *b = &ba; b->Display(); b->vDisplay(); b = &de; b->Display(); b->vDisplay(); |
…并按预期观察输出:
Base: Non-virtual display.
Base: Virtual display.
Base: Non-virtual display.
Derived: Virtual display.< /块引用>
是的,你有点误解了:
纯虚拟函数:
virtual void fun1()=0 ->必须在派生类中重写虚拟功能:
可以覆盖
virtual void fun2() ->正常功能:
void fun3() ->不要覆盖它为了实现运行时多态性,需要在C++中重写虚拟函数。
我认为在静态绑定和动态绑定的上下文中查看它可能更好。
如果该方法是非虚的(它已经默认在C++中不同于Java),那么该方法在编译时绑定到它的调用方,这是不可能知道将在运行时指向的实际对象的。所以,变量类型是所有重要的"基础"。