2014-10-16 121 views
5

我想知道为什么这段JAVA代码产生的输出不同于C++中的相同代码。这两个代码之间的区别?

#include "stdafx.h" 
#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    A(){ 
     this->Foo(); 
    } 
    virtual void Foo() 
    { 
     cout << "A::Foo()" << endl; 
    } 
}; 
class B : public A 
{ 
public: 
    B() 
    { 
     this->Foo(); 
    } 
    virtual void Foo() 
    { 
     cout << "B::Foo()" << endl; 
    } 
}; 
int main(int, char**) 
{ 
    B objB; 
    system("pause"); 
    return 0; 
} 

这将产生输出:

A::Foo() 
B::Foo() 

Java代码是:

public class Testa { 
    public Testa() 
    { 
     this.Foo(); 
    } 
    public static void main(String[] args) 
    { 
     Testb b = new Testb(); 
    } 
    void Foo() 
    { 
     System.out.println("A"); 
    } 

} 
class Testb extends Testa { 
    public Testb() 
    { 
     this.Foo(); 
    } 
    @Override 
    void Foo() 
    { 
     System.out.println("B"); 
    } 
} 

此代码仅产生

B 
B 

这是为什么输出在这种情况下不同?

+1

在C++中,你不应该在构造函数(或析构函数)中调用虚函数,我不会做太多的Java,所以我不会说这些。 – Borgleader 2014-10-16 19:26:02

+2

请注意,在C++代码中,您从两个构造函数中调用foo,而在Java代码中,您只能从Testb的构造函数调用它。 – Eran 2014-10-16 19:29:35

+0

哎呀,对不起,我输错了,一秒钟...... – 2014-10-16 19:30:56

回答

5

不同之处在于在施工期间处理多态性。在Java中,对象的动态类型是派生类的动态类型,允许您在构造函数有机会设置成员变量之前调用成员函数。这不好。

C++有一个不同的方法:虽然构造函数运行时,对象的类型被认为是构造函数所属类的一个类型。所有对成员函数的调用都是根据该假设静态解析的。因此,A的构造函数调用A::foo(),而B的构造函数调用B::foo()

2

编辑

我回答问题的第一部分给予被列入了Java Testa构造函数之前。


在Java代码中,你不必定义为你的C++代码Testa构造。这就解释了为什么只有一个B以Java打印。

但即使你做到了,以使代码更相当于:

public Testa() 
{ 
    this.Foo(); 
} 

这将打印

B 
B 

因为Java中的多态性的作品,即使该方法是从构造函数调用。但是这样做不是一个好主意,因为在Testb中调用方法Foo时,对象Testb的子部分仍将未初始化。

+0

好吧,你读了我的思想。所以这在C++中不能像这样工作? – 2014-10-16 19:32:30

+0

@MattJones不,它不。 – 2014-10-16 19:33:27

+1

@MattJones我比C++知道更多的Java;我不知道为什么C++的行为不同。但是我可以验证它在C++中打印了'A :: Foo()'和'B :: Foo()'。 – rgettman 2014-10-16 19:34:50