static_cast vs. reinterpret_cast für void*

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

static_cast vs. reinterpret_cast für void*

Beitrag von kaiserludi »

void* können sowohl mit static_cast, als auch mit reinterpret_cast in Pointer zu instanzen beliebiger Klassen gecastet werden, wobei es in der Verantwortung des Programmierers liegt, dass der Pointer auf ein gültiges Objekt der korrekten Klasse zeigt, wenn er dereferenziert wird.

Code: Alles auswählen

Foo* foo = NULL;
void* vp = foo
foo = static_cast<Foo*>(vp); // correct
foo = reinterpret_cast<Foo*>(vp); // also correct
Ist einer der beiden Casts aus irgendeinem Grund zu bevorzugen oder ist es reine Geschmackssache, welchen von den beiden man in dem Fall statt dem ebenfalls möglichen C-Cast nimmst?

EDIT: Fixed topic, meinte natürlich reinterpret, nicht dynamic
Zuletzt geändert von kaiserludi am 25.08.2011, 21:33, insgesamt 3-mal geändert.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
FlorianB82
Beiträge: 70
Registriert: 18.11.2010, 05:08
Wohnort: Darmstadt
Kontaktdaten:

Re: static_cast vs. dynamic_cast für void*

Beitrag von FlorianB82 »

aus meinem bauchgefühl heraus würde ich immer den schwächstmöglichen cast verwenden, d.h. static_cast.

edit: gerade nochmal näher drüber nachgedacht, und festgestellt, dass dynamic_cast an der stelle auch nicht wirklich sinn macht. das hier scheint dem rechtzugeben: http://www.gamedev.net/topic/492353-c-d ... -and-void/
Zuletzt geändert von FlorianB82 am 25.08.2011, 20:57, insgesamt 1-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: static_cast vs. dynamic_cast für void*

Beitrag von Krishty »

kaiserludi hat geschrieben:Ist einer der beiden Casts aus irgendeinem Grund zu bevorzugen oder ist es reine Geschmackssache, welchen von den beiden man in dem Fall statt dem ebenfalls möglichen C-Cast nimmst?
Afaik gibt es da keinen Unterschied. Aber das gilt wirklich nur für void * (und vielleicht für den artverwandten char *; habe die Paragraphen nicht griffbereit).

Falls du den Unterschied zwischen reinterpret_cast und static_cast wissen möchtest: reinterpret_cast gibt dieselbe Stelle im Speicher aus, die reingegeben wurde. Und das ist, auch, wenn es kontraintuitiv klingt, oft unerwünscht …:

Erbt beispielsweise eine Klasse Derived von zwei Klassen Base1 und Base2, dann wird das von vielen Compilern so realisiert, dass die Klassen gemäß ihrer Vererbungshierarchie im Speicher liegen – erst eine komplette Instanz von Base1 mitsamt Virtual Function Table / Type Information und dahinter allen ihren Attributen, dann dasselbe für Base2 und schließlich die Attribute, die Derived der Hierarchie hinzufügt. Die Funktionstabellen und Typinformationen sowohl vom Base1- als auch vom Base2-Teil werden mit den Funktionstabellen von Derived überschrieben (jedoch erst, nachdem Ds K’tor fertig ist!).

Übergibst du nun eine Instanz von Derived an eine Funktion, die Base2 erwartet, geschieht die Magie: Die Funktion bekommt nicht die Adresse des kompletten Base1-Base2-Derived-Blocks, sondern die des Base2-Abschnitts der Instanz. Ein polymorpher Typ ändert also unter Umständen seine Speicherposition, wenn man ihn zu einer seiner Basen zurückkonvertiert. Umgekehrt ändert ein Objekt möglicherweise seine Position, wenn man es zu einer ableitenden Klasse konvertiert.

Und da ist der Unterschied zwischen static_cast und reinterpret_cast: static_cast zieht das in Betracht und gibt einen Zeiger auf das gültige Objekt der Basisklasse oder abgeleiteten Klasse zurück; reinterpret_cast spuckt einfach denselben Zeiger mit anderem Typ aus und treibt dich damit wahrscheinlich früher oder später in die Hölle. (dynamic_cast verhält sich wie static_cast, nur, dass es durch die Funktionstabellen und Typinformationen sicherstellt, dass die Konvertierung gültig ist. Dadurch steigt aber übrigens auch seine Laufzeit von O(1) auf O(Vererbungstiefe zwischen den Klassen).)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
FlorianB82
Beiträge: 70
Registriert: 18.11.2010, 05:08
Wohnort: Darmstadt
Kontaktdaten:

Re: static_cast vs. dynamic_cast für void*

Beitrag von FlorianB82 »

wir halten fest: böser reinterpret_cast ;) (wobei das auch nur ein halbes augenzwinkern ist, reinterpret_cast sollte man tunlichst sparsam einsetzen...)

spass beiseite, super erklärung. irgendwie war mir das alles zwar so im hinterkopf, aber das hier bringt es auf den punkt.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: static_cast vs. dynamic_cast für void*

Beitrag von Krishty »

Und noch hinterher:

Daraus werden übrigens drei Optimierungsmöglichkeiten deutlich:
  1. Da die Funktionstabellen überschrieben werden, wenn die Konstruktion einer ableitenden Klasse abschließt, kann man bei Klassen, die ausschließlich über abgeleitete Klasse instanziert werden, (lies: Schnittstellen) die Erstinitialisierung der Funktionstabellen gleich ganz weglassen. Das Schlüsselwort für Visual C++ ist __declspec(novtable) und spart mir persönlich immer wieder eine ganze Menge Maschinentext.
  2. Wenn man wissen möchte, ob eine Schnittstelle zu einem bestimmten Typ gehört, ist typeid(Derived) == typeid(referenceToInterface) mit Laufzeit von O(1) schneller als nullptr != dynamic_cast<Derived *>(pointerToInterface), das erst alle Vererbungsstufen durchackern muss. Ganz abgesehen davon, dass es zwei Paar Schuhe sind, da ersteres angibt, ob eine Schnittstelle durch ganz genau diesen Typ implementiert ist; und zweiteres, ob die Schnittstelle durch irgendeinen Typ implementiert ist, der von diesem Typ erbt.
  3. Polymorphie ist scheißkomplex und falls man sie elegant vermeiden kann, sollte man es tun. Also alles immer schön einfach halten. Wenn man bspw. einen stringstream nur zum Formatieren braucht, stattdessen einen ostringstream benutzen, denn dessen Vererbungshierarchie ist nur halb so komplex. Falls man dennoch nicht um Polymorphie und Typinformation herumkommt: dynamic_cast und typeid sind trotz allem meist schneller und – vor allem – zuverlässiger und lesbarer als selbstgebauter Kram.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
FlorianB82
Beiträge: 70
Registriert: 18.11.2010, 05:08
Wohnort: Darmstadt
Kontaktdaten:

Re: static_cast vs. dynamic_cast für void*

Beitrag von FlorianB82 »

Krishty hat geschrieben:(dynamic_cast verhält sich wie static_cast, nur, dass es durch die Funktionstabellen und Typinformationen sicherstellt, dass die Konvertierung gültig ist. Dadurch steigt aber übrigens auch seine Laufzeit von O(1) auf O(Vererbungstiefe zwischen den Klassen).)
Krishty hat geschrieben:Polymorphie ist scheißkomplex
Das ist übrigens auch wieder ein argument dafür, sein vererbungshierarchien flach zu halten, und lieber vieles durch komposition/delegation zu machen, statt durch vererbung. (ich meinte, ich hätte letztens hier so eine diskussion gelesen, wo es darum ging, ob man einen der std container nun besser wrapt oder von ihm erbt...)

Und für mich persönlich auch ein argument, multiple inheritance zu vermeiden.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: static_cast vs. reinterpret_cast für void*

Beitrag von Krishty »

Ich will es auch nicht übertreiben; dynamic_cast frisst jetzt nicht irgendwie eine Million Takte weg oder so. In den meisten Anwendungen dürfte es auch garnicht ins Gewicht fallen. Bei Assimp haben wir durch Ersetzen von stringstream durch ostringstream ein paar Prozent Exe-Größe gespart; die Laufleistungsverbesserungen dürften komplett im Rauschen untergehen. Aber das sind eben Dinge, die man von vornherein ohne die geringste Einbuße an Funktionalität mitnehmen kann, und die das Gesamtpaket in der Masse ein bisschen schlanker werden lassen – wenn man denn nur weiß, dass man das kann. Man sollte die Lösung immer so minimalistisch wie möglich anpacken; egal, ob mit oder ohne Vererbung.

Bei sowas wie einem Compiler, der einen großen Zeitraum damit verbringt, die Ausdrücke eines Syntaxbaums zu ordnen, würde ich hingegen schon direkt messbare Verbesserungen erwarten, wenn man typeid statt dynamic_cast nutzt. Bei so extensiver Datenverarbeitung macht es halt schon einen Unterschied, ob man einfach nur zwei Zeiger vergleicht oder mindestens zwei Indirektionen mit Cache-Verfehlungen und rekursiven Funktionsaufrufen in Kauf nimmt.

Naja; my two Cents.

Übrigens, nochmal zum Thema: Das Standardkomitee hat den gefährlichen Casts extra die längsten Namen zugeordnet; reinterpret_cast ist wesentlich unangenehmer zu schreiben als static_cast. Da aber C-Casts die kürzeste Methode sind und bleiben, ist die ganze „man fühlt, wenn man was falsches macht“-Sache komplett für’n Popo.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: static_cast vs. dynamic_cast für void*

Beitrag von kaiserludi »

FlorianB82 hat geschrieben:aus meinem bauchgefühl heraus würde ich immer den schwächstmöglichen cast verwenden, d.h. static_cast.

edit: gerade nochmal näher drüber nachgedacht, und festgestellt, dass dynamic_cast an der stelle auch nicht wirklich sinn macht. das hier scheint dem rechtzugeben: http://www.gamedev.net/topic/492353-c-d ... -and-void/
Sorry, ging mir um reinterpret_cast, nicht um dynamic_cast.
Krishty hat geschrieben:
kaiserludi hat geschrieben:Ist einer der beiden Casts aus irgendeinem Grund zu bevorzugen oder ist es reine Geschmackssache, welchen von den beiden man in dem Fall statt dem ebenfalls möglichen C-Cast nimmst?
Afaik gibt es da keinen Unterschied. Aber das gilt wirklich nur für void * (und vielleicht für den artverwandten char *; habe die Paragraphen nicht griffbereit).

Falls du den Unterschied zwischen reinterpret_cast und static_cast wissen möchtest: reinterpret_cast gibt dieselbe Stelle im Speicher aus, die reingegeben wurde. Und das ist, auch, wenn es kontraintuitiv klingt, oft unerwünscht …
Der generelle Unterschied zwischen den beiden ist mir bekannt. Mir ist bloß gerade aufgefallen, dass ich bei void* keinen Unterschied feststellen konnte.
Also scheinbar wirklich Geschmackssache.
FlorianB82 hat geschrieben:
Krishty hat geschrieben:(dynamic_cast verhält sich wie static_cast, nur, dass es durch die Funktionstabellen und Typinformationen sicherstellt, dass die Konvertierung gültig ist. Dadurch steigt aber übrigens auch seine Laufzeit von O(1) auf O(Vererbungstiefe zwischen den Klassen).)
Krishty hat geschrieben:Polymorphie ist scheißkomplex
Das ist übrigens auch wieder ein argument dafür, sein vererbungshierarchien flach zu halten, und lieber vieles durch komposition/delegation zu machen, statt durch vererbung. (ich meinte, ich hätte letztens hier so eine diskussion gelesen, wo es darum ging, ob man einen der std container nun besser wrapt oder von ihm erbt...)

Und für mich persönlich auch ein argument, multiple inheritance zu vermeiden.
Ich würde das eher unterordnen bei der Frage, ob man einen Container nun wrappt oder von ihm erbt. Da gibt es genug andere Punkte, die für diese Entscheidung wichtiger sind (will man den Zugriff auf bestimmte API-Parts des Originals in seiner "Erweiterung" unterbinden, ist der Container überhaupt darauf ausgelegt, vererbt zu werden, etc. (z.B. kommt man bei Class Clustern gar nicht drumherum, entweder zu wrappen oder aber das Speichermanagment neu zu implementieren, das ist aber eher ein Problem, welcfhe in objC auftritt, wo Class Cluster dank Cocoa recht verbreitet sind), wenn man alles, was fürs wrappen spricht, verneinen kann und der Originalcontainer eine umfangreiche API hat, (welche man komplett übernehmen will), die sich womöglich auch noch ab und zu ändert, dann bietet es sich normalerweise eher an, zu erben, da man sich so einen Haufen Programmierarbeit gegenüber dem Wrappen spart).
eine Verebrungsebene mehr bringt einen in den meisten Situationen nicht um. Es sollte eben bloß nicht total ausufern.

Was multile Vererbung angeht:
Man braucht sie uwar selten und dann muss man wissen, was man tut, aber in Sprachen ohne sie habe ich die jeweilige Sprache deswegen schon oft genug verflucht und mir gewünscht, ich könnte für den Code C++ einsetzen, denn ab und zu hat man eben doch Situationen, in denen man viel tricksen und unintutive Umwege gehen muss, um an multipler Vererbung vorbei zu kommen.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: static_cast vs. reinterpret_cast für void*

Beitrag von kaiserludi »

Krishty hat geschrieben: Das Standardkomitee hat den gefährlichen Casts extra die längsten Namen zugeordnet; reinterpret_cast ist wesentlich unangenehmer zu schreiben als static_cast. Da aber C-Casts die kürzeste Methode sind und bleiben, ist die ganze „man fühlt, wenn man was falsches macht“-Sache komplett für’n Popo.
Mir wärs lieber, die wären kürzer. So kommt man nur immer in Versuchung, nen c-cast zu nutzen, um sich nicht die Finger wund zu tippen, insbesondere, wenn man statt dem C-Cast gleich 2 C++ Castgs bräuchte.
Ich habe da teilweise schon Code gehabt, da ging vor lauter reinterpret_cast<newType*>(const_cast<oldType*>(foo)) die ÜBersicht komplett verloren, weil man solche Dinger ein Dutzend mMal in einer endlos langen Zeile hatte, die vorher mit C-Casts geschrieben dagegen geradezu zierlich wirkte und viel leichter in dem was sie tut erfassbar war, typischerweise bei Schnittstellen zwsiachen const-korrektem C++ und const-losem C89.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
FlorianB82
Beiträge: 70
Registriert: 18.11.2010, 05:08
Wohnort: Darmstadt
Kontaktdaten:

Re: static_cast vs. reinterpret_cast für void*

Beitrag von FlorianB82 »

kaiserludi hat geschrieben:Sorry, ging mir um reinterpret_cast, nicht um dynamic_cast.
ah, damn. ich hatte lustigerweise auch erst reinterpret_cast angenommen, aber dann beim zweiten lesen den dynamic_cast bemerkt...
kaiserludi hat geschrieben:Ich würde das eher unterordnen bei der Frage, ob man einen Container nun wrappt oder von ihm erbt. Da gibt es genug andere Punkte, die für diese Entscheidung wichtiger sind
da hast du völlig recht. deswegen schrieb ich ja "auch" ein argument. dass es da noch viele andere gibt, die je nach situation verschieden stark wiegen, ist klar (man denke nur, man müsste std:string wrappen, viel spaß...).
kaiserludi hat geschrieben:aber in Sprachen ohne sie habe ich die jeweilige Sprache deswegen schon oft genug verflucht und mir gewünscht, ich könnte für den Code C++ einsetzen, denn ab und zu hat man eben doch Situationen, in denen man viel tricksen und unintutive Umwege gehen muss, um an multipler Vererbung vorbei zu kommen
mir war dieses glück noch nicht beschert, aber da hast du vermutlich einfach größere/kompliziertere software vor dir als ich =).
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: static_cast vs. reinterpret_cast für void*

Beitrag von kaiserludi »

FlorianB82 hat geschrieben:
kaiserludi hat geschrieben:aber in Sprachen ohne sie habe ich die jeweilige Sprache deswegen schon oft genug verflucht und mir gewünscht, ich könnte für den Code C++ einsetzen, denn ab und zu hat man eben doch Situationen, in denen man viel tricksen und unintutive Umwege gehen muss, um an multipler Vererbung vorbei zu kommen
mir war dieses glück noch nicht beschert, aber da hast du vermutlich einfach größere/kompliziertere software vor dir als ich =).
Beispiel, mit welchem ich dieses Jahr in objC schon viel Spaß hatte:
SomeContainer : Object; // gigantisch umfangreiche API
SomeMutableContainer : SomeContainer; // noch umfangreichere API als SomeContainer
SomeEnhancedFunctionalityContainer : SomeContainer; // noch umfangreichere API als SomeContainer
SomeMutableEnhancedFunctionalityContainer : SomeEnhancedFunctionalityContainer, SomeMutableContainer;
Ohne multiple Vererbung darf man da entweder die ganzen Methoden von der einen Basis oder die von der anderen wrappen, bzw., falls möglich, das gigantische Interface implementieren.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
FlorianB82
Beiträge: 70
Registriert: 18.11.2010, 05:08
Wohnort: Darmstadt
Kontaktdaten:

Re: static_cast vs. reinterpret_cast für void*

Beitrag von FlorianB82 »

kaiserludi hat geschrieben:Beispiel, mit welchem ich dieses Jahr in objC schon viel Spaß hatte:
SomeContainer : Object; // gigantisch umfangreiche API
SomeMutableContainer : SomeContainer; // noch umfangreichere API als SomeContainer
SomeEnhancedFunctionalityContainer : SomeContainer; // noch umfangreichere API als SomeContainer
SomeMutableEnhancedFunctionalityContainer : SomeEnhancedFunctionalityContainer, SomeMutableContainer;
nun, wenn man dann wirklich das jeweilige komplette interface wrappen muss (und nicht nur ein kleiner teil ausreicht, meistens komme ich so dann ganz gut weg), dann würde ich wohl auch den weg der MI wählen. das erscheint da ja dann das einfachste.

einfach bleibt das aber auch nur, wenn sich die interfaces bzw deren implementierung der beiden geschwisterklassen nicht im wege stehen; "Mutable" also möglichst orthogonal zu "EnhancedFunctionality" bleibt. anonsten wirds leicht furchtbar.

ich bin insgesamt halt einfach etwas vorsichtig mit vererbung; wie oft sieht man vererbungshierarchien, die so einfach falsch sind (sprich: dem LSP mal so gar nicht entsprechen), und die offensichtlich nur entstanden sind aus der denkweise: cool, so kann ich möglichst einfach und schnell meinen code wiederverwenden. dass vererbung nicht für code-wiederverwendung, sondern für polymorphie gut ist, wird oft übersehen. was dann raus kommt, ist fragwürdig. (und streng genommen hört sich das beispiel oben auch ersteinmal nach wiederverwendung an. klar könnte man das ganze dann auch polymorph verwenden, sofern die entsprechenden funktionen virtuell sind (gibt es das so in obj-c? davon habe ich keine ahnung...). wenn nicht (wie zum beispiel dei den containern der stl), dann ist das ganze zumindest theoretisch falsch.)
Benutzeravatar
FlorianB82
Beiträge: 70
Registriert: 18.11.2010, 05:08
Wohnort: Darmstadt
Kontaktdaten:

Re: static_cast vs. reinterpret_cast für void*

Beitrag von FlorianB82 »

(ich habe gerade das gefühl, ich/wir sind wirklich gut vom OP abgedriftet...)
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: static_cast vs. reinterpret_cast für void*

Beitrag von kaiserludi »

FlorianB82 hat geschrieben:
kaiserludi hat geschrieben:Beispiel, mit welchem ich dieses Jahr in objC schon viel Spaß hatte:
SomeContainer : Object; // gigantisch umfangreiche API
SomeMutableContainer : SomeContainer; // noch umfangreichere API als SomeContainer
SomeEnhancedFunctionalityContainer : SomeContainer; // noch umfangreichere API als SomeContainer
SomeMutableEnhancedFunctionalityContainer : SomeEnhancedFunctionalityContainer, SomeMutableContainer;
nun, wenn man dann wirklich das jeweilige komplette interface wrappen muss (und nicht nur ein kleiner teil ausreicht, meistens komme ich so dann ganz gut weg), dann würde ich wohl auch den weg der MI wählen. das erscheint da ja dann das einfachste.

einfach bleibt das aber auch nur, wenn sich die interfaces bzw deren implementierung der beiden geschwisterklassen nicht im wege stehen; "Mutable" also möglichst orthogonal zu "EnhancedFunctionality" bleibt. anonsten wirds leicht furchtbar.

ich bin insgesamt halt einfach etwas vorsichtig mit vererbung; wie oft sieht man vererbungshierarchien, die so einfach falsch sind (sprich: dem LSP mal so gar nicht entsprechen), und die offensichtlich nur entstanden sind aus der denkweise: cool, so kann ich möglichst einfach und schnell meinen code wiederverwenden. dass vererbung nicht für code-wiederverwendung, sondern für polymorphie gut ist, wird oft übersehen. was dann raus kommt, ist fragwürdig. (und streng genommen hört sich das beispiel oben auch ersteinmal nach wiederverwendung an. klar könnte man das ganze dann auch polymorph verwenden, sofern die entsprechenden funktionen virtuell sind (gibt es das so in obj-c? davon habe ich keine ahnung...). wenn nicht (wie zum beispiel dei den containern der stl), dann ist das ganze zumindest theoretisch falsch.)
Nö, gibt keien Virtualität in objC. objC ist für den Compiler reines C, bzw. objC++ für den Compielr reines C++. Der obj-Part, also alles mit Smalltalk-Syntax, wird per Präprozessor in C bzw. C++ umgewandelt. Entsprechend ist dort auch nur das möglich, was man ohen Compile rein per Präprozessor umsetzen kann.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Antworten