除了其他出色的答案外,还有一件非常重要的事情,并且通常被忽略/遗忘或被误解(这解释了为什么我在下面详细介绍该过程):
- 在Java中,方法是虚拟的,即使从构造函数中调用也是如此(这可能会导致错误)
- 在C ++中,当从构造函数调用虚拟方法时,虚拟方法不是虚拟的(这可能会引起误解)
什么?
- 让我们想象一个带有虚拟方法foo()的基类。
- 让我们想象一个继承自base的派生类,该类重写方法foo()
C ++和Java之间的区别是:
- 在Java中,从基类构造函数中调用foo()将调用Derived.foo()
- 在C ++中,从基类构造函数中调用foo()将调用base.foo()
为什么?
每种语言的“错误”都不同:
- 在Java中,调用构造函数中的任何方法都可能导致细微的错误,因为重写的虚拟方法可能会尝试访问在Derived类中声明/初始化的变量。
从概念上讲,构造函数的工作是使对象存在(这绝非普通的壮举)。在任何构造函数中,整个对象可能仅是部分形成的–您只能知道基类对象已被初始化,但是您无法知道从您那里继承了哪些类。但是,动态绑定的方法调用到达继承层次结构的“向前”或“向外”。它在派生类中调用方法。如果在构造函数中执行此操作,则调用一个方法,该方法可能会操纵尚未初始化的成员,这无疑是灾难的秘诀。
布鲁斯·埃克尔(Bruce
Eckel),http://www.preguru.com/java/tij/tij0082.shtml
- 在C ++中,必须记住虚函数无法按预期工作,因为仅会调用当前构造类的方法。原因是避免访问数据成员或什至尚不存在的方法。
在基类构造过程中,虚拟函数永远不会进入派生类。而是,该对象的行为就像是基本类型一样。非正式地说,在基类构建期间,虚拟函数不是。
斯科特·迈耶斯(Scott
Meyers),http://www.artima.com/cppsource/nevercall.html



