this im ctor

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Psycho
Establishment
Beiträge: 156
Registriert: 16.09.2002, 14:23

this im ctor

Beitrag von Psycho »

Hallo,

ich habe jetzt schon etwas gesucht aber nichts gefunden, was meine Fragen so richtig beantwortet.

Code: Alles auswählen

class A
{
  public:
    A(B &b) { b.registerMe(*this); }
};

class B
{
  public:
    void registerMe(A &a) { /* hier wird *beliebiges* mit dem Objekt a gemacht, also zB Aufruf virtueller Funktionen. */ }
};
Ich nehme an, dass das nicht immer das gewünscht Verhalten mit sich bringt? Worauf genau muss ich achten?
Und vor allem: Wie lässt sich das Problem vermeiden? Brauch ich eine Extra-Methode, die irgendwann nach dem Constructor aufgerufen wird?

Code: Alles auswählen

class A
{
  private:
    B m_b;

  public:
    A() : m_b(*this) :  { }
};

class B
{
  public:
    B(A &a) { /* hier wird *beliebiges* mit dem Objekt a gemacht, also zB Aufruf virtueller Funktionen. */ }
};
Ich meine sogar hier letztens was zu dem Thema gelesen zu haben, weiß aber leider nicht mehr genau wo.
Mir ist aber aufgefallen, dass ich in meinem Code öfter this in Contructors benutzt habe und bisher bin ich von Problemen verschont geblieben.
Zuletzt geändert von Psycho am 11.06.2009, 20:06, insgesamt 1-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: this im ctor

Beitrag von Krishty »

Hi,
Bitte {code=cpp} (mit eckigen Klammern) für die Tags benutzen :)

Das Problem ist nicht, dass this im K’tor ungültig wäre (ist es nicht, nur in Initialisierungslisten), sondern dass Klassenhierarchien bei der Basisklasse beginnend nach oben hin aufgebaut werden. Solange du dich im K’tor der Basisklasse befindest, ist dein Objekt vom Typ der Basisklasse (damit auch seine virtuellen Funktionen). Erst danach, wenn du im K’tor der abgeleiteten Klasse bist, kannst du auch auf die von dieser Klasse überschriebenen Funktionen zugreifen.

Da registerMe() vom K’tor der Basisklasse aus aufgerufen wird, verhält sich das Objekt dort auch exakt wie eines der Basisklasse. In dem Fall brauchst du tatsächlich eine Funktion, die erst nach der vollständigen Konstruktion aufgerufen wird.

Das Thema, das du meintest, war wahrscheinlich dieses hier.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Psycho
Establishment
Beiträge: 156
Registriert: 16.09.2002, 14:23

Re: this im ctor

Beitrag von Psycho »

Blöde Sache, ne?!
Genau, den Thread meinte ich, danke fürs Raussuchen.

Wie ist das eigentlich, ist das Objekt schon in nem gültigen Zustand, bevor der Constructor beendet wurde?

Code: Alles auswählen

    class A
    {
      private:
        B m_b;
        int i;

      public:
        A() : m_b(*this) :  { i = 0; }
        int getI() { return i; }
    };

    class B
    {
      public:
        B(A &a) { std::cout << a.getI(); }
    };
Hier zB. Ich habs jetzt nicht getestet, aber der Constructor von B wird wohl aufgerufen, bevor i auf 0 gesetzt wird, also wird die Ausgabe undefiniert sein.

Ich muss mal gucken, ob ich ein konkreteres Beispiel finde, aber gefühlsmäßig würde ich sagen, dass da Fälle dabei waren, wo ich auf die Extra-Methode und ihren Aufruf gerne verzichetet hätte. Aber wenns nicht anders geht, was solls..
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: this im ctor

Beitrag von Krishty »

Psycho hat geschrieben:Wie ist das eigentlich, ist das Objekt schon in nem gültigen Zustand, bevor der Constructor beendet wurde?
Kommt drauf an. Eigentlich sind Initialisierungslisten zu dem Zweck da, dass jedes Member eines Objekts in einem garantiert gültigen oder ungültigen (aber nicht zufälligen) Zustand ist, wenn man anfängt, Code auf dem Objekt auszuführen. Hast du einen guten K’tor, ist das Objekt schon beim Betreten des {-}-Blocks deines K’tors vollständig initialisiert („vollständig“ lässt natürlich abgeleitete Klassen außen vor, aber die kennt man dort ja auch noch nicht).

Zum konkreten this-Problem in deinem Beispiel: http://www.parashift.com/c++-faq-lite/c ... l#faq-10.7 (letzter Abschnitt).
Ich kenne die präzisen Regeln nicht. Mein Compiler (Visual Studio 2008) gehört zu der Gruppe, die eine Warnung anzeigt, wenn ich this in der Initialisierungsliste verwende, daher vermeide ich es, soweit es geht.

Den Grund für diese Warnung kenne ich nicht, ich würde aber vermuten, dass bei einer solchen Verwendung eben nicht mehr sicher gestellt werden kann, dass das Objekt vollständig initialisiert ist, wenn der Aufruf erfolgt. Wäre schön, wenn das einer unserer Experten erklären könnte :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Unknown GER
Beiträge: 49
Registriert: 09.01.2003, 13:04

Re: this im ctor

Beitrag von Unknown GER »

Wurde ja schon fast alles gesagt. :) Eine Initialisierungsliste wird vor dem Konstruktor abgearbeitet, auch eine implizite, d. h. wenn man keine Liste schreibt oder Elemente auslässt (Initialisierung findet in der Reihenfolge der Deklarationen der Membervariablen der Klasse statt und wenn nichts explizit angegeben wird mit dem jeweiligen Defaultkonstruktor). Mit dem Start des Konstruktors ist die Klasse dann schon komplett aufgebaut, alles was nun kommt ist optional und nichts weiter als Zuweisungen und Methodenaufrufe. This ist (erst) dann auch gültig da man ja i. A. unter anderem auch schon Methoden der Klassen aufrufen lassen, die als versteckten ersten Parameter den this-Zeiger annehmen. ABER, never ever virtuelle Methoden von Konstruktoren oder Destruktoren aus aufrufen. Es wird dann nämlich die Methode der Klasse aufgerufen, in dessen Konstruktor man sich gerade befindet (Konstruktoren von abgeleiteten Klassen werden ja erst nach den Konstruktoren ihrer Basisklassen aufgerufen). Das passiert schneller, als man denkt (siehe Dein Beispiel).
Antworten