2014-10-16 20 views
5

Mi stavo chiedendo perché questo pezzo di codice JAVA produca un output diverso rispetto allo stesso codice in C++.Differenza tra questi 2 codici?

#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; 
} 

Questo produce l'uscita:

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

il codice 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"); 
    } 
} 

Questo codice produce solo

B 
B 

Perché questo output diverso in questo caso ?

+1

In C++ non si dovrebbero chiamare funzioni virtuali nel costruttore (o distruttore), io non faccio molto Java, quindi non parlerò su questo. – Borgleader

+2

Si noti che nel codice C++ si sta chiamando da entrambi i costruttori, mentre nel codice Java si sta chiamando solo dal costruttore di Testb. – Eran

+0

Oops, scusa ho sbagliato, un secondo ... –

risposta

5

La differenza sta nella gestione del polimorfismo durante la costruzione. In Java, il tipo dinamico dell'oggetto è quello della classe derivata immediatamente, consentendo di chiamare la funzione membro ancor prima che il costruttore abbia la possibilità di impostare le variabili membro. Questo non va bene.

C++ ha un approccio diverso: mentre viene eseguito il costruttore, il tipo dell'oggetto considerato è quello della classe a cui appartiene il costruttore. Tutte le chiamate alle funzioni membro vengono risolte staticamente in base a tale ipotesi. Di conseguenza, il costruttore di A chiama A::foo(), mentre il costruttore di B chiama B::foo().

2

Modifica

La prima parte della mia risposta è stato dato prima del costruttore Java Testa è stato incluso.


Nel codice Java, non hanno un costruttore Testa definita nel codice C++. Ciò spiega perché solo uno B viene stampato in Java.

Ma anche se l'avete fatto, per rendere il codice più equivalente:

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

Sarebbe stampare

B 
B 

Perché in Java il polimorfismo funziona anche quando il metodo viene chiamato dal costruttore. Ma non è una buona idea farlo perché la parte secondaria dell'oggetto Testb sarà ancora non inizializzata quando il metodo Foo viene chiamato in Testb.

+0

Ok, mi stai leggendo.Quindi questo non funziona così in C++? –

+0

@MattJones no, non è così. –

+1

@MattJones Conosco più Java che C++; Non so perché C++ si comporta diversamente. Ma posso verificare che stampa 'A :: Foo()' e 'B :: Foo()' in C++. – rgettman

Problemi correlati