2013-10-17 13 views
6

Si consideri il seguente programmaPerché pA, pB, pC non sono uguali?

#include<iostream> 
using namespace std; 
class ClassA 
{ 
public: 
    virtual ~ClassA(){}; 
    virtual void FunctionA(){}; 

}; 

class ClassB 
{ 
public: 
    virtual void FunctionB(){}; 
}; 



class ClassC : public ClassA,public ClassB 
{ 

}; 

void main() 
{ 
    ClassC aObject; 
    ClassA* pA = &aObject; 
    ClassB* pB = &aObject; 
    ClassC* pC = &aObject; 

    cout<<"pA = "<<pA<<endl; 
    cout<<"pB = "<<pB<<endl; 
    cout<<"pC = "<<pC<<endl; 

} 

pA, pB, pc si suppone alla parità, ma il risultato è

pA = 0031FD90

pB = 0031FD94

Pc = 0031FD90

wh y pB = pA + 4? e quando cambio

class ClassA 
{ 
public: 
    virtual ~ClassA(){}; 
    virtual void FunctionA(){}; 

}; 
class ClassB 
{ 
public: 
    virtual void FunctionB(){}; 
}; 

a

class ClassA 
{ 
}; 

class ClassB 
{ 
}; 

il risultato è

pA = 0030FAA3

pB = 0030FAA4

pC = 0030FAA3

pB = pA + 1?

+0

penso che questo ti aiuterà, http://stackoverflow.com/questions/254673/multiple-inheritance-from-two-derived-classes – shankar

risposta

1

L'oggetto con più proprietà ereditate ha due oggetti secondari uniti. Vorrei indovinare il compilatore sta puntando uno dei puntatori a un oggetto interno.

0

C ha due sottooggetti ereditati, pertanto è la concatenazione di un oggetto A e un oggetto B. Quando hai un oggetto C, è composto da un oggetto A seguito da un oggetto B. Non si trovano nello stesso indirizzo, ecco perché. Tutti e tre i puntatori indicano lo stesso oggetto, ma come diverse superclassi. Il compilatore fa il turno per te, quindi non devi preoccuparti di questo.

Ora. Perché c'è una differenza di 4 in un caso e 1 in un altro? Bene, nel primo caso, hai funzioni virtuali sia per A che per B, quindi ogni sottooggetto deve avere un puntatore al suo vtable (la tabella che contiene gli indirizzi delle chiamate di funzioni virtuali risolte). Quindi in questo caso, sizeof(A) è 4. Nel secondo caso, non hai funzioni virtuali, quindi non vtable. Ma ogni sottooggetto deve essere indirizzabile in modo indipendente, quindi il compilatore deve ancora allocare per un diverso indirizzo per subobject di classe A e subobject di classe B. Il minimo di differenza tra due indirizzi è 1. Ma mi chiedo se EBO (vuota base-class ottimizzazione) non dovrebbe essere calciato in questo caso.

+0

probabilmente ha a che fare con alcuna ottimizzazione specificato al momento della compilazione. – Raja

0

Questo è il dettaglio di implementazione del compilatore. Il motivo per cui hai riscontrato questo caso è perché hai MI nel tuo codice.

Pensa a come il computer accede al membro in ClassB, utilizzando l'offset per accedere al membro. Quindi supponiamo di avere due int nella classe B, usando la seguente istruzione per accedere al secondo membro int.

*((int*)pb + 1) // this actually will be assembly generate by compiler 

Ma se il pb punto per l'inizio del aObject nella classe, questo non funzionerà più, in modo che il compilatore ha bisogno di generare versioni multiple di montaggio per accedere alla stessa base membro sulla struttura ereditare classe e avere un costo di runtime

Ecco perché il compilatore regola pb non uguale a pa, il che farà funzionare il codice di cui sopra, è il modo più semplice ed efficace per implementare.

E questo spiega anche perché pa == pc ma non è uguale a pb.

Problemi correlati