这2个代码之间的区别?

时间:2014-10-16 19:24:54

标签: java c++ inheritance

我想知道为什么这条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

为什么在这种情况下输出会有所不同?

2 个答案:

答案 0 :(得分:5)

不同之处在于在构造过程中处理多态性。在Java中,对象的动态类型是派生类的动态类型,允许您甚至在构造函数有机会设置成员变量之前调用成员函数。这很糟糕。

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

答案 1 :(得分:2)

修改

我的回答的第一部分是在包含Java Testa构造函数之前给出的。


在Java代码中,您没有像C ++代码中那样定义Testa构造函数。这就解释了为什么只有一个B用Java打印。

但即使你这样做,也要使代码更具等效性:

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

会打印

B
B

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