Wie funktioniert Typedef?
-
Typo3 schrieb:
...Warum ist das so?...
Weil ein typedef eben nicht dasselbe ist wie ein #define.
Es "bindet stärker" als ein const....Ist übrigens ein Grund, warum ich immer dringend von "Pointer-typedefs" abrate (auch, wenn sie nicht ganz so gräßlich sind wie "#define-typedefs"): Sie verhalten sich nicht immer so, wie erwartet.
typedef string STRING1; typedef char* STRING2; void f(const STRING1); void f(const STRING2);.. die beiden f haben unterschiedliche Parametersemantik !
Gruß,
Simon2.
-
Simon2 schrieb:
Ist übrigens ein Grund, warum ich immer dringend von "Pointer-typedefs" abrate
Mal davon abgesehen, dass ich den Nachteil nicht verstehe (das ist doch vielmehr das intuitive Verhalten): Was bietest Du als Alternative?
Ich benötige die Zeiger-Typedefs einfach, weil ich den Zeiger-Typ austauschbar halten muss. Daher habe ich Folgendes in einem Code:
// config.hpp, allgemeine Konfiguration des Projekts: // Diese Definition kann sich ändern! template <typename T> struct ptr { typedef boost::shared_ptr<T> type; };// fwd.hpp, enthält einige Vorwärtsdeklarationen: #include "config.hpp" struct expression; struct reference; struct value; // … #define EXPR_PTR_ALIAS(name) typedef ptr<name>::type p_##name; EXPR_PTR_ALIAS(expression) EXPR_PTR_ALIAS(reference) EXPR_PTR_ALIAS(value) #undef EXPR_ALIAS_PTR… wie könnte ich das besser machen? Überall die ausführliche Schreibweise
ptr<xyz>::typezu verwenden, bläht den Code unheimlich auf und macht ihn extrem unleserlich (ich habe es versucht – es war einfach furchtbar).
-
Sehe ich auch so, was wuerde man in der generischen Programmierung unter C++ ohne typedefs machen?!
Edit: Simon2 redet aber auch nur von "Pointer-Typedefs". Und ein shared_ptr<irgendwas> ist kein Pointer, genauso wie ein std::vector kein array ist.
Edit2: @Simon2 Ich komm mit deiner Aussage ueber "Pointer-Typedefs" nicht ganz klar. Kannst du das bitte mal fuer mich praezisieren bzw. mal ein konkretes Codebeispiel geben, bei denen die beiden typedefs zu Problemen fuehren. Danke

-
Simon2 schrieb:
Ist übrigens ein Grund, warum ich immer dringend von "Pointer-typedefs" abrate (auch, wenn sie nicht ganz so gräßlich sind wie "#define-typedefs"): Sie verhalten sich nicht immer so, wie erwartet.
typedef char* STRING2;Ich glaube das Problem hier ist, dass du durch einen Typedef die speziellen Eigenschaften eines char-Pointers für den Leser unsichtbar werden lässt, so dass er mit falschen Erwartungen an diesen Typ herangeht. Mit typedefs auf Pointer hat das an sich nichts zu tun, nur mit sinnvoller Namensgebung.
Davon abgesehen ist es natürlich oft ein Rückschlag in längst vergangene Pascal-Tage, zwanghaft typedefs auf Pointer einzuführen. Man sieht das zum Glück immer seltener.
-
Gut, das sehe ich auch so mit der sinnvollen Namensgebung. BTW ich finde deine Signatur toll Bashar

-
um die scheinbare Ungereimtheit mit den Pointertypedefs und anschließender const-Deklaration zu vermeiden, kann man es sich angewöhnen, const grundsätzlich nach dem als const zu deklarierenden Typen zu schreiben, also statt
const int i;dann
int const;. Dann wird aus typedefs nämlich
typedef int* Iptr; Iptr const iptr; //klar, das ist int* const, also ein constanter Zeiger auf intZugegeben, ich habs bisher erst in einem Buch gesehn, dass das auch umgesetzt wurde (Josuttis/Vandervoorde, "C++ Templates, a complete guide"), aber es öst eben das Problem. Ob es sinnvoll ist, das umzusetzen, sei jedem selbst überlassen, allerdings empfinde ich persönlich Dinge wie
foo foo::operator=(foo const& other); //seltsame Art, eine const reference zu deklarieren)als die größere Stolperfalle beim Lesen im Vergleich zu den doch eher selten vorkommenden Pointer typedefs.
-
Bashar schrieb:
...
Ich glaube das Problem hier ist, dass du durch einen Typedef die speziellen Eigenschaften eines char-Pointers für den Leser unsichtbar werden lässt, so dass er mit falschen Erwartungen an diesen Typ herangeht. ...Genau DAS meinte ich: Das "Verstecken" der Pointersemnatik des Typs.
Passiert natürlich viel bei char*, ich habe es aber auch schon öfter bei anderen Typen gesehen (2. Rang: void, gibt aber noch mehr).Und das (also das Verstecken) finde ich fatal.
Wenn aus dem Typ(namen) noch klar hervorgeht, dass er als Zeiger zu handeln ist, finde ich das voll OK. (z.B bei Funktionspointern erhöht IMHO oftmals die Lesbarkeit, ohne eine andere Semantik zu suggerieren).
Gruß,
Simon2.
-
pumuckl schrieb:
Ob es sinnvoll ist, das umzusetzen, sei jedem selbst überlassen, allerdings empfinde ich persönlich Dinge wie
foo foo::operator=(foo const& other); //seltsame Art, eine const reference zu deklarieren)als die größere Stolperfalle beim Lesen im Vergleich zu den doch eher selten vorkommenden Pointer typedefs.
Stolperfalle? Ich mache das immer so. Und zwar aus dem ganz einfachen Grund, dass ich es einheitlicher finde, 'const' stets postfix anzugeben, denn bei Funktionsdeklarationen steht 'const' ja auch postfix, und wenn man da mischt, sieht das komisch aus:
void f(const t&) const; // versus void g(t const&) const;
-
Wie gut, daß C bzw. C++ beides erlaubt (const als Prä- und Postfix).
So kann es jeder machen, wie er will und man kann sich schön über den "unleserlichen" Code von anderen aufregen
P.S. Ich persönlich nutze 'const' als Präfix, quasi als einleitendes Schlüsselwort.
So daß ein konstanter Zeiger auf ein konstantes Objekt dann quasi symmetrisch ist:const A * const pA; // Edit: * entfernt (wollte nur einen Einfach-Zeiger darstellen)
-
Th schrieb:
const A * const * a;Was dann ein non-const-Zeiger auf einen const-Zeiger auf ein const-Objekt waere

Ist denke ich mal Geschmackssache, wie man es nun macht. Man wird sich dran gewoehnen muessen, dass man es mal als Prae- und mal als Postfix zu lesen bekommt, wenn man sich fremden Code anschaut. Fuer sich selber sollte man es auf jeden Fall konsistent halten, wenn man mit mehreren an einem groesseren Projekt arbeitet moeglichst projektweit einheitlich.
-
Th schrieb:
Wie gut, daß C bzw. C++ beides erlaubt (const als Prä- und Postfix)...
Naja ... aber nur auf den ersten Qualifizierer. Ansonsten ist es ja immer postfix...
Vielleicht wäre es schon, es IMMER als Präfix zu haben, da es aber nunmal so ist, wie es ist, präferiere ich da auch ein einheitliches Postfix.
Gruß,
Simon2.