2012-07-23 9 views
5

Ich arbeite an einem meiner Anwendungsproblem. Hier ist das Problem, mit dem ich konfrontiert bin, gibt es einige Funktionen, die ich mit dem Zeiger eines Klassenobjekts aufrufen muss.Adresse eines Objekts in C++ und seine Mitglieder

Aber das Hauptproblem ist, ich donot haben einen Klassenzeiger mit mir, stattdessen habe ich einen Mitgliedsvariablenwert (lassen Sie uns sagen, es ist eine Liste von Werten). Danach habe ich einen kleinen Test mit dem folgenden Code gemacht.

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

Die coutput der Ausführung ist:

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

Nun meine Zweifel:

Ist sichergestellt, dass die Adresse der Klassenvariable an die Adresse des Objekts zeigt immer? Kann ich diese Adresse für den Fall verwenden, dass ich den Zeiger für den Aufruf anderer Core-API-Funktionen verwenden muss?

Ich sah das, als ich googelte?

(C1x §6.7.2.1.13: "Ein Zeiger auf ein Strukturobjekt, entsprechend konvertiert, zeigt auf seinen Anfangsmember ... und umgekehrt. Möglicherweise gibt es ein unbenanntes Padding innerhalb als Strukturobjekt, aber nicht als sein Anfang. ")

ist das auch im Fall von C++ und Klassen wahr?

+1

Siehe Offset des Makros. Nur für POD-Typen! –

+0

Für jeden Klassentyp hat jedes Datenelement einen festen Offset-Wert.Dies ist nicht die Startadresse des Objekts, da der Compiler einige Dinge an die Spitze legt. Aber das wird anders, wenn Sie virtuelle Funktionen haben, da der Compiler das vptr * auch in das Objekt schreiben muss. Also mache ich es nicht generell gut, diesen Weg zu gehen. – madu

+1

kann verwandt sein: http://stackoverflow.com/questions/8240273/a-portable-way-to-calculate-pointer-to-the-whole-structure-using-pointer-to-a-fi – user396672

Antwort

7

Ist garantiert, dass die Adresse der Klassenvariablen stets auf die Adresse des Objekts zeigt?

Nein. In C++ gibt es potenziell Zeug vor dem ersten Mitglied (insbesondere für abgeleitete Klassen und polymorphe Klassen). Was genau dort ist, ist die Implementierung definiert.

Kann ich diese Adresse verwenden, falls ich den Zeiger zum Aufruf anderer Kern-API-Funktionen verwenden muss?

Nein, und Sie müssen nicht: Wann immer Sie Zugang zu Mitgliedern haben, haben Sie auch Zugriff auf this, nein?

+0

Leider Nein. Ich habe einen Zeiger auf das letzte Blatt des Baumes Ich habe nur Eltern-Schlüssel und mit dem Eltern-Schlüssel Ich kann die Liste der Kinder, die es hat, die eine Liste ist und die ein Mitglied der Klasse ist.Dies kann als a gesagt werden Baum, aber es ist keine tatsächliche Baumimplementierung. – Vijay

+0

@peter Das ist unklar. Aber die Antwort bleibt gleich. Sie können * einen Zeiger auf ein Element nicht als Zeiger auf die Klasse verwenden. Dies führt zu ungültigem C++ - Code, der unterbrochen wird. –

1

Dies gilt auch für Klassen, sofern sie keine virtuellen Funktionen haben. Auch sollten Sie darauf achten, ob Sie Vererbung haben (nicht sicher, wie genau die Regeln da sind).

Im Allgemeinen ist dies jedoch eine schlechte Idee. Warum willst du das machen? Sie verlassen sich auf die Struktur der Klasse (dh Ihr Code wird kaputt gehen, wenn Sie zufällig ein Mitglied vor dem Alter hinzufügen) und Sie verschenken Kapselung (keine andere Klasse sollte sowieso einen Zeiger zum Altern haben, da es privat ist - Sie würden sich leakieren Objektdarstellung).

Btw: Sind Sie ein Java-Programmierer? Ihr Konstruktor sieht aus wie Sie sind, da Sie Ihr Objekt nicht korrekt initialisieren. Sie sollten es tun, wie folgt:

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

(sonst wird der Compiler den Standard contstructors von int und String zuerst anrufen und dann Operator ruft = auf sie - das ist nicht effizient).

Verwandte Themen