Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Template nicht rechtzeitig initialisiert

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
29.07.2008, 01:15 Uhr
~Gast2008
Gast


Hallo!

Ich komme einfach nicht dahinter... :( ...ich verstehe nicht warum
PreInitData.data, welche in B.cpp als Parameter an den Konstruktor
von p übergeben wird, dort nicht bereits mit 100.0 initialisiert ist?

Wäre toll wenn mir das jemand erklären könnte, danke! :)



C++:
// Datei A.h

#pragma once

template <class T> class A {
  public :

  T data;  

  static const A<T> PreInitData;

  A(T x);
};


template <class T> const A<T> A<T>::PreInitData(100.0);


template <class T> A<T>::A(T x) {
  data= x;
}




C++:
// Datei A.cpp (leer)

#include "A.h"




C++:
// Datei B.h

#pragma once

#include "A.h"

class B {
  static A<float> p;
};




C++:
// Datei B.cpp

#include "B.h"

A<float> B::p(A<float>::PreInitData.data);

 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
29.07.2008, 19:02 Uhr
0xdeadbeef
Gott
(Operator)


Bei normalen Variablen könntest du dich darauf verlassen, dass sie innerhalb der selben Übersetzungseinheit in Reihenfolge initialisiert werden, aber nicht einheitsübergreifend; mit templates ist das ganze deutlich haariger, weil hier erst auf Anfrage überhaupt erzeugt wird. Die Reihenfolge, in der das hier geschieht, ist nicht standardisiert.

Du kannst allerdings den selben Mechanismus wie im Meyers-Singleton benutzen:

C++:
template<typename T> struct A {
  T data;

  static A const &PreInitData() {
    static A data(100);
    return data;    
  }

  A(T x);
};


...und dann

C++:
A<float> B::p(A<float>::PreInitData().data);


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
30.07.2008, 17:19 Uhr
~Gast2008
Gast


Danke für deine Antwort!

Angenommen ich entferne den dynamischen initialisierungs-Teil
via selbst deklarierten Konstruktor aus A.h wie folgt:


C++:
// Datei A.h

#pragma once

template <class T> class A {
  public :

  T data;  

  static const A<T> PreInitData;

  A(T x);
};


template <class T> const A<T> A<T>::PreInitData= 100.0;


template <class T> A<T>::A(T x) {
  data= x;
}



Selbst dann bekomme ich in B.cpp noch ne 0.0 statt 100.0.
Und das will mir einfach irgendwie nicht in den Kopf, ich meine
bevor in B.cpp überhaupt A<float> verwendet werden kann,
muss die ja vorher bereits erzeugt worden sein. Und bei
diesem Erzeugen muss doch der statische Variablen-"Kram"
initialisiert worden sein? Ich checks einfach irgendwie nich
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
30.07.2008, 17:30 Uhr
0xdeadbeef
Gott
(Operator)


Nein, muss er nicht. Die Initialisierungsreihenfolge ist im Standard nicht spezifiziert. Wenn du statische Variablen miteinander initialisieren willst, mach's so wie oben - da ist garantiert, dass das Objekt initialisiert wird, wenn die Funktion zum ersten mal aufgerufen wird.

Davon aber ganz abgesehen - globale Variablen bringen einen Haufen Probleme mit sich. Ich würde mir an deiner Stelle nochmal genau überlegen, ob du sie da tatsächlich brauchst.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
30.07.2008, 19:05 Uhr
0xdeadbeef
Gott
(Operator)


Nachtrag dazu:

Der Grund, warum es mit normalen statischen Variablen so nicht geht, ist, dass der Compiler nur die eine Übersetzungseinheit kennt, und nicht entscheiden kann, welche zur Laufzeit nachher zuerst initialisiert werden muss. Außerdem gibt es syntaktisch korrekte Konstrukte, die semantisch keinen Sinn ergeben und die ganze Geschichte böse durcheinander brächten - stell dir zum Beispiel

C++:
// header
extern int a, b;

// source 1
int a = b;

// source 2
int b = a;


vor. Mit Templates sind die Regeln deutlich komplexer, weil die ja erst zu Klassen/Funktionen konkretisiert werden müssen - dementsprechend ist

C++:
template <class T> const A<T> A<T>::PreInitData= 100.0;


noch keine Instanziierung von A<float>::PreInitData - dem Compiler wird erst bekannt, dass er die bauen soll, wenn sie zum ersten mal benutzt wird. Wenn ich den Standard richtig lese, ist in deinem Fall ist zu diesem Zeitpunkt die Deklaration von B::p für den Compiler vor der von A<float>::PreInitData vorhanden, und so wird B::p vor A<float>::PreInitData gebaut. Dass du dabei 0.0 als Wert kriegst, ist allerdings eine Besonderheit deines Compilers, der kann dir da prinzipiell alles mögliche andrehen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
31.07.2008, 16:28 Uhr
~Gast2008
Gast


Ok ich denke ich habs verstanden, vielen Dank!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: