关于如何在派生类的虚函数中调用被覆盖掉的同名基类的虚函数

很久没写BLOG了,这是在设计实现中遇到的一个实际问题,就是类似下面的Java代码在C++中如何实现的问题

 1 import java.io.*;
 2 import java.util.*;
 3 
 4 class B
 5 {
 6     public void Print()
 7     {
 8         System.out.println("B");
 9     }
10 }
11 
12 class D extends B
13 {
14     public void Print()
15     {
16         super.Print();
17         System.out.println("D");
18     }
19 }
20 
21 class Main
22 {
23     public static void main(String[] args)
24     {
25         B obj= new D();
26         obj.Print();
27     }
28 }
29 

有时候我们需要将所有子类方法中都会执行的代码放到基类方法中,或者可能这些代码是操作基类成员的本来就不应该放在子类,在Java中可以通过super来调用被覆盖掉的父类中的方法。

我居然以为C++无法实现这一点,实在是太无知了。Google之后才知道原来可以这样用

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class B
 5 {
 6 public:
 7     virtual void Print()
 8     {
 9         puts("B");
10     }
11 };
12 
13 class D:public B
14 {
15 public:
16     virtual void Print()
17     {
18         B::Print();
19         puts("D");
20     }
21 };
22 
23 int main()
24 {
25     B* p=new D();
26     p->Print();
27 }
28 

让我认为C++无法实现这点是有理由的,我们把virtual去掉看以下的代码
 1 #include <iostream>
 2 using namespace std;
 3 
 4 class B
 5 {
 6 public:
 7     void Print()
 8     {
 9         puts("B");
10     }
11 };
12 
13 class D:public B
14 {
15 public:
16     void Print()
17     {
18         ((B*)(this))->Print();
19         puts("D");
20     }
21 };
22 
23 int main()
24 {
25     D* p=new D();
26     p->Print();
27 }
28 

这段代码是可以正确实行的,因为没有virtual,D类中的Print并没有覆盖B类中的Print,只是同名而已(这是很不好的做法,容易产生误解),所以这时不存在运行时绑定,我只好D* p=new D(); 我认为子类对象在内存中是这样的



但是virtual的方法会被覆盖掉,也就是说对于D类的对象,已经没有B类的Print方法了。所以如果加上virtual我们就无法正确执行上面的代码了。

可是B::Print(); 又是如何实现的呢?
posted @ 2009-06-24 16:42  dzqabc  阅读(951)  评论(0编辑  收藏  举报