先来看一下这两个程序:
代码1: //TestA.java
class A { protected int num; public A() { init(); num = 1; } protected void init(){ System.out.println("i am A"); System.out.println(num); } }
class B extends A { public B(){ init(); num = 2; } protected void init(){ System.out.println("i am B"); System.out.println(num); } }
class TestA { public static void main(String[] args) { B b = new B(); } }
------ 代码2: //TestA.cpp
#include <iostream> using namespace std;
class A { protected: int num; public: A() { init(); num = 1; } protected: virtual void init() { cout << "i am A" << endl; cout << num << endl; } };
class B:public A { public: B() { init(); num = 2; } protected: void init() { cout << "i am B" << endl; cout << num << endl; } };
int main() { B b; return 0; } ------
代码1的编译运行结果如下(j2sdk 1.4.2): i am B 0 i am B 1
代码2的编译运行结果如下(g++ 3.3.1): i am A 0 i am B 1
发现不同了吧。
对于代码1,java采用的是动态绑定技术。构建子类B对象的时候,先调用基类A的构造函数,而A的构造函数中调用了init()方法,此时对java来说还是在构建B对象的过程中,因此这个调用的init()方法不是基类A中的而是B中的。
对于代码2,有点不同。虚函数在C++中原本是用来实现动态联编的,但在构造函数中调用虚函数时,采用的不是动态联编而是静态联编,即基类A的构造函数中的init()调用的是自己的init()方法。
另:把TestA.cpp中的virtual关键字去掉,看看运行结果,和没有去掉之前不一样,这是什么原因?有谁知道能告诉我吗?

|