Posted on 2009-03-25 23:00
魔のkyo 阅读(5025)
评论(1) 编辑 收藏 引用
很久没写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();
又是如何实现的呢?