假设我有两个C++类:
class A
{
public:
A() { fn(); }
virtual void fn() { _n = 1; }
int getn() { return _n; }
protected:
int _n;
};
class B : public A
{
public:
B() : A() {}
virtual void fn() { _n = 2; }
};
Run Code Online (Sandbox Code Playgroud)
如果我写下面的代码:
int main()
{
B b;
int n = b.getn();
}
Run Code Online (Sandbox Code Playgroud)
人们可能期望将n其设置为2.
事实证明,n设置为1.为什么?
在一次采访中,我得到了以下代码:
public abstract class Base {
public int x = 1;
public Base() {
foo();
}
public abstract void foo();
}
public class Derived extends Base {
int x = 2;
@Override
public void foo() {
System.out.println("Derived: "+x);
}
}
class Main {
public static void main(String... args) {
Base base = new Derived();
base.foo();
}
}
Run Code Online (Sandbox Code Playgroud)
他们问过:
什么会打印?
如果我们使用C++,我认为代码应该给出编译错误,因为Derived首先调用构造函数时,Base会调用类的构造函数.此时该foo方法不存在.
另外我知道在创建所有变量之前,首先调用继承的类构造函数.
但是在Java中我们得到:
Derived: 0 Derived: 2
为什么?
我知道像在C++中一样,Java继承始终基于虚拟表,并且在Base类的构造函数之前调用类的构造函数Derived.