Es ist nicht möglich const Member einer Klasse zu deklarieren die nicht statisch sind ??
-
1. Nicht-statische konstante Datenmember einer Klasse sind (ebnso wie Referenzen, bei denen noch andere Gründe dazukommen) nur äußerst selten gerechtfertigt. Häufig werden diese Member irrtümölich nur deshalb als const deklariert, weil geplant ist, die Klasse selbst nur mit const-Objekten zu verwenden. Das ist kein ausreichender Grund, ein mechanisches const-Hinschreiben, nur weil man es kann, ist auch nicht geeignet, Fehler zu vermeiden.
Ausschlaggebend sollte vielmehr sein, ob die const-Eigenschaft das Members, unabhängig davon besteht, ob das Objekt, zu dem es gehört const ist oder nicht. Nach meiner Erkenntnis ist das nur selten der Fall - prototypisch gilt es z.B. für Proxyobjekte.2. Es ist mit dem gegenwärtigen Standard nicht möglich, nichtstatische Arraymember in der Ctor-Initialisierungsliste zu initialisieren (außer Defaultinitialisierung). Weil nichtstatische const-Member aber stets dort initialisiert werden müssen, sind Klassen mit nichtstatischen konstanten rraymembern praktisch nicht verwendbar. Eine Ausnahme besteht lediglich im Falle von Aggregaten, die per Aggregat-Initialiserungsliste initialisiert werden können (auf diese Weise könnte man das Array doch wieder initialisieren, wenn man es in eine eigene Klasse verpackt, ich sehe darin allerdings wenig Sinn).
struct arrayholder { const int x[3]; } class foo { ... arrayholder arr; foo() : arr(get_arr() /* hier RVO */) { ... } arrayholder get_arr() { arrayholder x = { 0, 1, 2 }; return arr; /*hier NRVO */ } ... }
-
Okay. Danke.
Das es das nicht gibt hat mir viel weiter geholfen.
Dann passe ich selber auf meine Zugriffe auf.
Es ist nichts zwingendes, hatte lediglich gehofft der compiler würde mir die Arbeit abnehmen.
Bei mir ist
Klassenvariable = KLassenspezifisch
Membervariable = Objektspezifisch.
Also in eure Worten müßte es glaube ich heißen
-Ich benötige ein Zweidimensionales char array,
dessen zweite Dimension dynamisch angefordert werden muß.
-Das Zweidimensionale Array soll objektspezifisch sein.
-Die Größe des dynamisch angeforderten Speichers darf nur in Ausnahmefällen verändert werden. Muß an sonsten aber immer konstanst sein. Ausnahme fall meint, dass ich es explizit machen können muß. Also Mit new und delete, da diese Operatoren bei mit überschrieben sind.
-Die pointer der dynamisch angeforderten char arrays(nicht der Inhalt) würde ich jetzt gerne const machen, um zu vermeiden, dass ich, während ich memberfunktionen schreibe, welche auf die Arrays zugreifen nicht den Pointer verändere, und damit Speicherzugriffsfehler verursache oder speicherlöcher erzeuge. Die Zugriffprüfung wäre dann eben während des compilierens, und nicht während der Programmlaufzeit was für mcih besser wäre.Soweit ich das jetzt mitbekomen habe gibt es das aber nicht.
Es ist auch immer eine Frage zwischen aufwand und nutzen. Das Programm an sich wird sich dadurch const nicht ändern. Lediglich wann der fehler entdeckt wird.Gruß
-
pumuckl schrieb:
AlexXXx schrieb:
Grundsatzdiskussionen sind gerade zu langwierig. Des weiteren kommt meißt was dabei raus, was garnicht so funktioniert wie ich es gerne hätte.
Genau in so einer Grundsatzdiskussion stecken wir gerade, weil du ein Geheimnis aus deinen Zielen machst und uns nicht verrätst wie du es denn gern hättest. (Sondern nur was du gerne hättest, und das gibts nicht, zumindest nicht in C++)
Genau. Lustig, wenn man mit seinem Versuch gerade das erreicht, was man unbedingt vermeiden wollte.
AlexXXx schrieb:
@Nexus
Deine Idee hört sich gut an, aber ich verstehe sie nicht.Ich hatte ursprünglich sowas gemeint, aber bin mir nicht sicher, ob das noch auf dein Problem zutrifft:
class MyClass { public: MyClass() : MyArray(CreateArray()) { } private: std::tr1::array<Irgendwas, Anzahl> CreateArray() const; private: const std::tr1::array<Irgendwas, Anzahl> MyArray; };
AlexXXx schrieb:
Also in eure Worten müßte es glaube ich heißen
-Ich benötige ein Zweidimensionales char array,
dessen zweite Dimension dynamisch angefordert werden muß.Vielleicht sowas wie
std::tr1::array<std::vector<Irgendwas>, Anzahl>
? Zumindest würde ich Zugriffe pernew
unddelete
auf jeden Fall kapseln.*Edit: Zweiter Templateparameter bei
std::tr1::array
*
-
@Camper
Wow.
Danke für geniale Antwort
Den Quelltext werde ich mir Kopieren und merken. Für meine Klasse ist
der Aufwand aber nicht gerechtfertigt. Aber genau das bräuchte ich.Gruß Alex
-
Member mit const char*[3] anlegen. Im Constructor fuer jeden Eintrag neuen Speicher anfordern und mittels const_cast, das const entfernen. Zuweisen ... (so in etwa). Ich halte das Vorgehen trotzdem fuer fragwuerdig aber C++ verbietet dir fuer gewoehnlich nichts.
-
knivil schrieb:
Im Constructor fuer jeden Eintrag neuen Speicher anfordern und mittels const_cast, das const entfernen. Zuweisen ... (so in etwa). Ich halte das Vorgehen trotzdem fuer fragwuerdig aber C++ verbietet dir fuer gewoehnlich nichts.
Das ist dennoch kein Grund, undefiniertes Verhalten zu riskieren, gerade wenn es schönere Möglichkeiten gibt.
-
@Nexus
Danke für Antwort. Ich mußte erst recherchieren um folgen u können.
std::tr1::array war mit bis jetzt unbekannt.
Das müßte auch hin hauen.Gruß
-
AlexXXx schrieb:
@Camper
Wow.
Danke für geniale Antwort
Den Quelltext werde ich mir Kopieren und merken. Für meine Klasse ist
der Aufwand aber nicht gerechtfertigt. Aber genau das bräuchte ich.Gruß Alex
Beachte aber, dass ich im Quelltext etwas gemacht habe, wogegen ich darüber argumentiert habe. Besser wäre sicherlich, x in arrayholder nicht-const zu halten, während arr (für das man z.B. noch op[] überladen könnte) in foo const sein sollte.
tr1::array ist im Grunde so ein Arrayholder, nur noch etwas weiter aufgebohrt.
-
Tachyon schrieb:
Ich kann mir auch nicht vorstellen, das Breymann das so geschrieben hat.
Doch hat er:
Ullrich Breymann C++ eine Einführung (5.aktualisierte und erweiterte Auflage)
Kap 7.2.1 Klassenspezifische KonstanteKlassenspezifische Variable müssen außerhalb der Klassendefinition definiert und inititalisiert werden. Dies gilt nicht für klassenspezifische Konstanten, für die der Compiler keinen Platz anlegen muss, weil er direkt ihren Wert einsetzen kann, In C++ ist diese Ausnahme jedoch auf integrale und Aufzählungstypen beschränkt:
class KlasseMitKonstanten { enum RGB {rot = 0x0001, gelb = 0x0002, blau = 0x0004 }; static const unsigned int maximaleAnzahl = 1000; // Verwendung zum Beispiel: static int CArray[maximaleAnzahl]; // ...
Diese Konstanten werden innerhalb der Klassendefinition initialisiert. Auch wenn das Schlüsselwort static fehlt (siehe enum), sind sie für alle Objekte einer Klasse gleich, also klassen- und nicht objektspezifisch
Ende des Kapitels.
Aber in seiner neuen Auflage leicht geändert und bei GoogleBooks lesbar Ullrich Breymann C++ eine Einführung
Ich glaub ich brauch mal ein neues C++Buch...
-
Nexus schrieb:
Das ist dennoch kein Grund, undefiniertes Verhalten zu riskieren, gerade wenn es schönere Möglichkeiten gibt.
Ja, okay ... vielleicht: Member mit const char** anlegen, mittels new char*[3] anfordern neues Arrary anfordern, 3 weitere char-arrays anfordern und entsprechend den Elementen von char*[3] zuweisen. Danach char*[3] dem const char** zuweisen. So besser bzgl. undefiniertem Verhalten? Keine Frage, dass die Array-Template besser ist.
-
Ich muss hier nochmals nachhaken:
In allen Büchern die ich gelesen habe Beymann, Stroustrup... steht ausdrücklich das const auf Elementmember (in Klassen) nur auf statischer Ebene erlaubt ist.
Nach Stroustup (Auflage 2009)
class X { static const int = 0; // Ok; const int; // fehler da static fehlt static const float = 0.1L; // fehler da kein int - Wert };
es sieht so aus das (wenn Stroustrup für den C++ Standard und für das C++ Standardisierungsgremium steht) die Compiler sich schlicht nicht daran halten, das Selbe steht ja auch im Breymann. Also machen wir hier etwas was nicht offiziell vom C++Standard abgesegnet ist, oder nicht?
-
Ich glaube, du verwechselst da was. Initialisierung direkt in der Klassendefinition ist nur bei statischen integralen Konstanten erlaubt.
Natürlich darf man
const
-qualifizierte Klassenmember haben, sowohl statisch als auch nicht-statisch.
-
DeepCopy schrieb:
Nach Stroustup (Auflage 2009)
Welches Kapitel?
Das Zitat des Breymann ist irreführend, dann solche Aufzählungskonstanten sind zwar Member der Klasse, in der sie definiert werden, aber keine Variablen. Die Unterscheidung zwischen statisch/nicht-statisch ist von vornherein nur bei Objekten und Memberfunktionen sinnvoll, schließlich unterscheiden wir auch nicht zwischen statischen- und nicht-statischen Typen (genaugenommen tun wir das schon, nur in einem ganz anderen Zusammenhang...).
-
Ok, ich glaube ich habs, die Bücher Spechen von der Initialisierung von konstanten Elementen und von Elementkonstanten und meinen dabei zwei verschiedene Arten von Elemente
class X { const int i; // konstantes Element static const int j; // Elementkonstante }
[EDIT: "Welches Kapitel?" @camper auch für dich]
Sie dazu auch "Stroustrup" mann.. widersprüchlicher hätte man sich im Deutschen nicht ausdrücken können.
-
DeepCopy schrieb:
Ok, ich glaube ich habs, die Bücher Spechen von der Initialisierung von konstanten Elementen und von Elementkonstanten und meinen dabei zwei verschiedene Arten von Elemente
Das liest du falsch:
Das Kapitel heißt: Elementkonstanten (Englische Version: Member Constants)
Das ist als informeller Oberbegriff für alle Datenelemente, die auf irgendeine Weise konstant sind, gemeint.
Dabei wird zuerst der spezielle Fall der statischen integralen Elementkonstanten (oder synonym: des statischen integralen konstanten Elements) zuerst behandelt, nämlich dass hier die Initialisierung bereits bei dessen Deklaration erfolgen kann (komischerweise wird der Fall der statischen konstanten Aufzählungsvariablen nicht erwähnt).
Schließlich zweitens Aufzählungskostanten (enumerator).
Über andere Formen von konstanten Elementen wird in dem Kapitel nichts gesagt, schlicht weil dafür keine besonderen Regeln gelten.Persönlich mag ich die Übersetzung von member mit Element nicht, weil ich Elemente eher mit Arrays oder Containern im Allgemeinen assoziiere. Das ist der Grund, weshalb ich es in meine Beiträgen immer unübersetzt lasse.