2012-07-23 15 views
5

Sto lavorando su uno dei miei problemi di applicazione. Qui il problema che sto affrontando è che ci sono alcuni gruppi di funzioni che ho bisogno di chiamare usando il puntatore di un oggetto di classe.Indirizzo di un oggetto in C++ e relativi membri

Ma il problema principale è che non ho un puntatore di classe con me, invece ho un valore di variabile membro (diciamo che è un elenco di valori). in seguito ho fatto un piccolo test con il codice seguente.

using namespace std; 

class Person { 
public: 
     Person(string name, int age) { 
      this->name = name; 
      this->age = age; 
     } 
     string getName() { 
      return name; 
     } 
     int getAge() { 
      return age; 
     } 
     void Print() 
     { 
     printf("This address is %x\n",this); 
     printf("age adress is %x\n",&age); 

     } 
private: 
     int age; 
     string name; 

}; 

int main() { 
     cout << "Creating a person..." << endl; 

Person *johnDoe=new Person("John Doe", 25); 
     cout << "Person's name: " << johnDoe->getName() << endl; 
     cout << "Person's age: " << johnDoe->getAge() << endl; 
     johnDoe->Print(); 
     delete johnDoe; 
     return 0; 
} 

La coutput dell'esecuzione è:

> ./a.out 
Creating a person... 
Person's name: John Doe 
Person's age: 25 
This address is 72918 
age adress is 72918 

Ora il mio dubbio è:

E 'garantito che l'indirizzo della variabile membro della classe indica sempre l'indirizzo dell'oggetto? Posso usare questo indirizzo nel caso in cui ho bisogno di usare il puntatore per chiamare altre funzioni di core api?

Ho visto questo quando ho cercato su Google?

(C1X §6.7.2.1.13: "Un puntatore a un oggetto struttura, opportunamente convertito, indica al suo membro iniziale ... e viceversa Ci può essere senza nome imbottitura all'interno come oggetto la struttura, ma non a. il suo inizio. ")

è vero anche in caso di C++ e classi?

+1

Vedere offset della macro. Solo per i tipi POD! –

+0

Per ogni tipo di classe, ogni membro dei dati avrà un valore di offset fisso.Questo non è l'indirizzo di partenza dell'oggetto in quanto il compilatore mette alcune cose in alto. Ma questo sarà diverso quando si hanno funzioni virtuali come il compilatore ha bisogno di mettere il vptr * anche nell'oggetto. Quindi non è generalmente una buona pratica farlo in questo modo. – madu

+1

può essere correlato: http://stackoverflow.com/questions/8240273/a-portable-way-to-calculate-pointer-to-the-whole-structure-using-pointer-to-a-fi – user396672

risposta

7

È garantito che l'indirizzo della variabile membro della classe punti sempre verso l'indirizzo dell'oggetto?

No. In C++, ci sono cose potenzialmente prima del primo membro (in particolare per le classi derivate e le classi polimorfiche). Ciò che esattamente esiste è l'implementazione definita.

Posso usare questo indirizzo nel caso in cui ho bisogno di utilizzare il puntatore per chiamare altre funzioni di core api?

No, e non è necessario: ogni volta che si ha accesso ai membri, si ha anche accesso a this, no?

+0

Purtroppo No. Ho un puntatore per l'ultima foglia dell'albero ho solo la chiave genitore e utilizzando la chiave genitore posso ottenere l'elenco dei bambini che ha che è una lista e che è un meber della classe.Questo può essere detto come un albero ma non è una vera e propria implementazione dell'albero. – Vijay

+0

@peter Non è chiaro. Ma la risposta rimane la stessa. Non è possibile * utilizzare un puntatore a membro come puntatore alla classe. In questo modo, il codice C++ non valido si interromperà. –

1

Questo vale anche per le classi, a meno che non abbiano funzioni virtuali. Inoltre dovresti fare attenzione se hai ereditarietà (non sei sicuro di come esattamente le regole ci sono).

In generale, questa è una cattiva idea. Perché vuoi farlo? Ti affidi alla struttura della classe (cioè il tuo codice si interromperà se aggiungi per errore un membro prima dell'età) e lasci l'incapsulamento (nessun'altra classe dovrebbe avere un puntatore per invecchiare comunque, dato che è privato - ti perderesti rappresentazione dell'oggetto).

Btw: sei un programmatore Java? Il tuo costruttore sembra come te, dal momento che non inizializzi correttamente l'oggetto. Si dovrebbe fare in questo modo:

Person(String n, int a) : age(a), name(s) {} 

(altrimenti il ​​compilatore prima chiamare i contstructors di default di int e la stringa e quindi chiamare operatore = su di loro - questo non è efficiente).

Problemi correlati