C ++和Java对象模型之间的差异


问题内容
  1. 在Java中,序列化对象非常容易。在C memcpy,只要对象像C结构一样就安全(?)(无多态性)。在C 中, 如果编译器能够生成默认的(琐碎的)复制构造函数,那么为什么它不能生成用于自动序列化的代码?

  2. 在Java中,只能从ctor访问静态函数和数据成员。 在C ++中,我可以愉快地使用ctor中的非静态成员和函数。

  3. 在Java中,我可以在类中内联初始化数据成员。在C ++中,这是一个编译错误。

  4. 在Java中,我可以final在ctor中初始化成员。在C 中,我必须对const初始化列表中的成员进行初始化。 **在C 中,当控制权到达ctor的主体时,ctor的所有成员都已运行,对吗?**

  5. 在Java中,一个ctor可以调用另一个ctor。在C ++中,我们无法做到这一点。

  6. 在Java中,this直到ctor返回(this引用的转义,多线程中的错误)后才有效。什么时候this在C 中有效?在this可以很容易地用C逸出两个和Java中: 在构造函数登记尚未构造的对象,以监听器 (观察者模式)。

  7. 在Java中,我无法在派生类中将基类的公共函数设为私有。令我震惊的是,在C ++中还可以,甚至有用。

有人可以对这些差异做一个简短的解释吗?

更新。 到目前为止,试图收集答案。

  1. Boost具有一些类似序列化的支持。(托尼)

  2. 尽管我弄明白了这一点,但Alf P. Steinbach还是举了一个有趣的例子。

  3. C 0x比C 98支持更多实用的初始化。(Alf P.Steinbach)#3在C ++ 0x中是合法的(Ken Bloom)

  4. 确保在构造函数的{body}开始执行时已完全构造了在构造函数的自己的类中声明的数据成员。(c ++-faq-lite)

  5. C 0x将允许构造函数调用其他对等构造函数(Wikipedia,C 0x)

  6. 当C ++ 03的构造函数完成执行时,它认为该对象将被构造(Wikipedia)。

  7. 诸如访问控制之类的东西与对象模型无关:这是访问控制系统的一个功能,即编译时功能。(Yttrill)


问题答案:

在Java中,序列化对象非常容易。在C ++中,对对象而言,只要它们像C结构一样,就安全(?)(没有多态性)。

Java是一种解释型语言(或者,最近更新为Billy的评论,由JIT编译),因此它别无选择,只能在运行时随身携带程序中每种数据类型的元数据包。在解释器,VM,可选编译器和元数据开销之间,Java程序需要大量内存。C
是一种编译语言,其中Java做出的许多决定都是在编译时做出的,而元数据并不能在运行时进行解释以指导序列化。通常,即使在编译时也不会公开元数据,这可能是因为不同的编译器供应商对程序的建模完全不同,并且他们还没有集体协商出合适的表示形式。这也是一项艰巨的工作。Bjarne
Stroustrup有一些有关如何公开这些信息的论文,但是甚至没有计划用于C
0x。与此同时,

在Java中,我可以在类中内联初始化数据成员。在C ++中,这是一个编译错误。

每个C
++构造函数都提供有关如何初始化对象的完整,独立的视图。如果值得的话,可以将常见的构造步骤分解为支持例程,但是对它的调用在构造函数中仍然可见。尽管一定很方便,但是必须检查分散在班级中的各种作业,这会使它脱离本地化。这里很多,我很危险。

在Java中,我可以在ctor中初始化最终成员。在C ++中,我必须对初始化列表中的const成员进行初始化。

这反映了const成员是使用其唯一值创建的,并且不会从某些不确定或null状态过渡到初始化状态。

在Java中,一个ctor可以调用另一个ctor。在C ++中,我们无法做到这一点。

是的,有时在C 中有点烦人-特别是对于需要在初始化程序列表中的引用和const,但是您可以将其他常见的构造步骤纳入支持函数。我认为C的位置反映了构造函数在构造基,成员,指向虚拟调度表的指针等方面的工作。在机器代码级别,不一定可以从另一个构造函数调用一个构造函数并执行正确的步骤。可能需要编译器生成另一个可从另一个构造函数调用的版本,或内联被调用构造函数的正确部分,但这有点隐藏。

在Java中,我无法在派生类中将基类的公共函数设为私有。令我震惊的是,在C ++中还可以,甚至有用。

如果您承认它很有用,也许Java应该添加它。

有人可以对这些差异做一个简短的解释吗?

好吧,我试过了。