Function overloading and virtual method table
Possible Duplicate:
What is the slicing problem in C++?
我有一个简单的代码作为多态性和继承的例子
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 | class A { public: int fieldInA; void virtual overloadedFunc() { printf("You are in A "); } }; class B : public A { public: int fieldInB; void overloadedFunc() { printf("You are in B "); } }; void DoSmth(A* a) { a->overloadedFunc(); } void DoSmthElse(A a) { a.overloadedFunc(); } int _tmain(int argc, _TCHAR* argv[]) { B *b1 = new B(); B b2; //Breakpoint here DoSmth(b1); DoSmthElse(b2); scanf("%*s"); return 0; } |
当我在断点处停止时,b1的_vptr[0]和b2的_vptr[0]的值相同(someaddr(b::overloadedfunc(void))。在dosmth()中传递b1作为参数后,局部变量a的vptr[0]仍然是someaddr(b::overloadedfunc(void)),但dosmthelse中a的vptr[0]现在是someaddr(a::overloadedfunc(void))。我确信这是我对函数重载概念的一些误解,但我不明白,为什么在第一种情况下我看到"你在B"而在第二种情况下看到"你在A"。a*b1=new b();dosmth(b1);//你在b,为什么?
首先,你需要正确使用你的术语!您没有重载任何函数,您超越了它们:
- 重载意味着您具有相同的函数名和不同类型的参数。选择正确的重载是一个编译时操作。
- 重写意味着你有一个多态的类层次结构(C++中的EDCOX1,24个)函数,并且用一个适用于一个更专业的对象的函数来替换被调用的函数。你超越了原来的意义。选择正确的覆盖是一个运行时操作,在C++中使用类似于虚拟函数表的操作。
这些术语足够混乱,甚至使事情变得更糟,它们甚至相互作用:在编译时,选择正确的重载,最终调用虚拟函数,从而可能被重写。此外,重写派生类可能会隐藏从基类继承的重载。不过,如果你不能弄清楚这些条款,所有这些都可能毫无意义!
现在,对于您的实际问题,当您调用
要获得多态行为,需要在指向基类的指针或引用上调用虚拟函数,而不是基类的实例。当你调用这个函数时
1 | void DoSmthElse(A a) |
你通过了一个
在
1 | a->overloadedFunc(); |
执行,因为虚拟函数