2009-01-14 9 views
27

Kann ich "this" innerhalb des Klassenkonstruktors an eine Funktion als Zeiger übergeben und damit auf die Mitglieder des Objekts zeigen, bevor der Konstruktor zurückkehrt?Weitergabe von "this" an eine Funktion innerhalb eines Konstruktors?

Ist dies sicher, solange die aufgerufenen Mitglieder vor dem Funktionsaufruf ordnungsgemäß initialisiert werden?

Als Beispiel:

#include <iostream> 

class Stuff 
{ 
public: 
    static void print_number(void *param) 
    { 
     std::cout << reinterpret_cast<Stuff*>(param)->number; 
    } 

    int number; 

    Stuff(int number_) 
     : number(number_) 
    { 
     print_number(this); 
    } 
}; 

void main() { 
    Stuff stuff(12345); 
}

Ich dachte, das würde nicht funktionieren, aber es scheint. Läuft dieses Standardverhalten oder nur undefiniertes Verhalten auf meinem Weg?

Antwort

30

Wenn Sie ein Objekt in C++ instanziieren, wird der Code im Konstruktor zuletzt ausgeführt. Alle anderen Initialisierungen, einschließlich Superklasseninitialisierung, Superklassenkonstruktorausführung und Speicherzuordnung, werden vorher ausgeführt. Der Code im Konstruktor dient nur dazu, eine zusätzliche Initialisierung durchzuführen, sobald das Objekt konstruiert ist. Daher ist es durchaus zulässig, einen "This" -Zeiger in einem Konstruktor einer Klasse zu verwenden und anzunehmen, dass er auf ein vollständig konstruiertes Objekt zeigt.

Natürlich müssen Sie sich vor nicht initialisierten Membervariablen hüten, wenn Sie sie nicht bereits in Ihrem Konstruktorcode initialisiert haben.

+4

Halbwahr. Denken Sie zweimal darüber nach, bevor Sie dies in einem Konstruktor verwenden, insbesondere wenn etwas von der Klasse abgeleitet werden könnte. In diesem Fall arbeiten Sie mit einer partiell konstruierten Klasse und virtuelle Aufrufe sind, afaik, undefined. Dasselbe gilt für den allgemeinen 'Klassenstatus': Der abgeleitete Konstruktor kann ihn immer noch modifizieren. – user52875

4

Sie können eine gute Antwort auf diese here (C++ FAQ) finden.

Alle geerbten Mitglieder und Mitglieder der aufrufenden Klasse sind garantiert am Anfang der Codeausführung des Konstruktors erstellt worden und können somit sicher darin referenziert werden.

Das Hauptproblem ist, dass Sie keine virtuellen Funktionen unter this aufrufen sollten. Meistens habe ich es versucht, aber es endet damit, dass ich die Funktion der Basisklasse aufruft, aber ich glaube, dass der Standard sagt, dass das Ergebnis nicht definiert ist.

+0

Der Link scheint nicht zu funktionieren ... –

+0

Er ist nicht definiert für reine virtuelle Funktionen (die noch keine Definition haben). –

-2

Andy, ich glaube, du liegst falsch im undefinierten Teil des Standards. Wenn Sie sich im Konstruktor befinden, ist "dies" ein Zeiger auf ein Objekt, dessen Typ Basisklasse des Objekts ist, das Sie erstellen, was bedeutet, dass virtuelle Funktionen teilweise in der Basisklasse implementiert sind aufgerufen und die Zeiger in der virtuellen Tabelle werden nicht gefolgt.

Mehr Informationen im C++ Faq Lite ...

+0

Falsch: Wenn Sie Derived :: Derived eingeben, zeigt this -> bereits auf ein Derived-Objekt. Dies unterscheidet sich von z.B. Java, wo dies. kann auf das MostDerived-Objekt zeigen. In keiner Sprache wird this-> auf "a" Basisklasse im Konstruktor von Derived zeigen.Auch mit MI, auf welche Basis würde dies zeigen? – MSalters

0

Als Randnotiz auf dem Code präsentiert, würde ich stattdessen templatize die void*:

class Stuff 
{ 
public: 
    template <typename T> 
    static void print_number(const T& t) 
    { 
     std::cout << t.number; 
    } 

    int number; 

    Stuff(int number_) 
    : number(number_) 
    { 
     print_number(*this); 
    } 
}; 

Dann würden Sie einen Compiler-Fehler, wenn die Typ t hat kein number Mitglied.

Verwandte Themen