DIY-Array: Schreiben ja, Größe ändern nein



  • Hallo,
    ich habe mir mal eine nicht ganz ernst gemeinte Array-Klasse geschrieben. Es gibt eine resize()-Funktion und den []-Operator.
    Ist es irgendwie möglich das Array so zu erstellen, dass man es zwar wie gewohnt beschreiben kann, aber nicht seine größe ändern kann?? Also zususagen halb-const!?
    Die resize()-Funktione ganz weg lassen ist natürlich keine Option. 😉

    MfG
    ULong


  • Mod

    ULong schrieb:

    Die resize()-Funktione ganz weg lassen ist natürlich keine Option. 😉

    Was soll denn passieren, wenn jemand die resize-Funktion benutzt?



  • Soll genau genommen resize(int size) sein..
    Naja die Größe soll sich ändern. Aber das würde ich ab und zu gerne verbieten.

    MfG
    ULong



  • Und nu?



  • ULong schrieb:

    Soll genau genommen resize(int size) sein..
    Naja die Größe soll sich ändern. Aber das würde ich ab und zu gerne verbieten.

    MfG
    ULong

    Dann biete doch zwei Klassen an, ein ResizableArray und ein FixedArray.



  • Ich denke SeppJs Frage bezog sich darauf was passieren soll wenn man resize aufruft, obwohl es gesperrt ist. Im einfachsten Fall kann man in der Klasse einfach ein Lock-Flag setzen und wenn man dann versucht resize zu benutzen gibts eine Exception oder sowas. Komplizierter wirds wenn du zur Compilezeit über den Fehler benachrichtigt werden willst.



  • Zu Volkards Methode: Sehe ich das richtig, dass ich dann z.B. auch alle Funktionen, die ein "DIY-Array" erwarten doppelt schreiben muss?? Das wäre natürlich ungünstig, würde sonst aber etwas weniger Ballast mitschleppen, auch wenn ein bool nicht wirklich viel ist..

    Das mit dem Lock-Flag habe ich mir auch schon so ähnlich überlegt. Ich dachte man könnte da schon früher ansetzen. Am new-Operator, od irgendwie mit const eben.
    ..Ich war nichtmal davon ausgeangen, dass es überhaupt möglich ist, einen Fehler zur Compilezeit festzustellen..



  • Code Example zu volkards Vorschlag (außer ich hab das Missverstanden).
    Einfach die OOP verwenden, dann muss nichts doppelt geschrieben werden.

    class FixedArray {
    public:
      void set();
    }
    
    class ResizeableArray : public FixedArray {
    public:
      void resize(int);
    }
    

    Oder nicht?



  • Hmm hmm hmm.. Auch nicht schlecht.

    Ich habs auch mit Vererbung versucht. Aber andersrum..: Vom array mit resize() ableiten und dann resize() überschreiben.

    Tja jetzt gibt es also schon 3 Möglichkeiten:
    1. Array+resize() -> Ableitung -> resize() überschreiben
    2. Array ohne resize() -> Ableitung -> zusätzlich resize()
    3. Array ohne Ableitung mit "noResize"-Flag

    Jetzt mal direkt als Frage in die Runde: Wenn ihr vor der Wahl stündet, welche Möglichkeit würdet ihr nehmen .. und warum (Vorteile/Nachteile)?



  • Ich würde eine ganz normale Klasse schreiben, die dein vergrößertes Array darstellt, aber nur mit den nötigsten Operationen - Elementzugriff, Größenabfrage, Größe setzen, Iteratoren, falls du die brauchst.

    Dann eine zweite Klasse, die ist dein Array ohne Größenveränderung. Das nimmt einfach dein Array mit Größe, speichert es als Member und forwarded alle Funktionen außer resize.

    Auf gar keinen Fall public Vererbung für so etwas verwenden!



  • Nathan schrieb:

    Auf gar keinen Fall public Vererbung für so etwas verwenden!

    Aus welchem Grund?



  • Public Vererbung stellt eine "Ist-ein"-Beziehung dar.
    Ein ResizableArray ist ein FixedArray. Passt irgendwie nicht. Entweder Resizable oder Fixed, beides geht nicht.



  • patrick246 schrieb:

    Public Vererbung stellt eine "Ist-ein"-Beziehung dar.
    Ein ResizableArray ist ein FixedArray. Passt irgendwie nicht. Entweder Resizable oder Fixed, beides geht nicht.

    Namen sind schall und rauch. Wenn aus dem Klassennamen "FixedArray" der Klassenname "Array" wird, würde das wieder passen "ist-ein".
    ResizeableArray ist ein Array.

    Gibt es ein anderer Grund der gegen dieses Design spricht?



  • ULong schrieb:

    Tja jetzt gibt es also schon 3 Möglichkeiten

    Ich hab noch eine: Ein Templateparameter der angibt ob das Array Fixed oder Resizable ist. Bei dem Fixed Size Array dann die resize Funktion mit SFINAE deaktivieren.



  • nebler schrieb:

    Gibt es ein anderer Grund der gegen dieses Design spricht?

    Erfahrung. 😃
    Der Code ist trivial. Durch rumerben machste Dir zu viel Arbeit und baust Abhängigkeiten, sodaß Du nicht mehr ganz einfach beim einen was dazutun kannst, ohne das andere zu stören.
    Vererbung ist hier fehl am Platz, esd ist keine IST-EIN-Beziehung.


  • Mod

    Ich sehe keinen Grund, überhaupt etwas zu verbieten, wenn es möglich ist. Zwischen Arrays mit "echt" fixer Größer und dynamischen Arrays gibt es einen Unterschied und man sollte die Wahl haben, was man braucht. Aber wozu sollte man jemals ein dynamisches Array haben wollen, bei dem die Größenänderung künstlich verboten wurde?

    Selbst wenn du irgendeinen Grund an den Haaren herbei ziehst, hast du immer noch nicht meine Frage beantwortet. Sie war so gemeint, wie sebi707 sie interpretiert hat.



  • Zwischen Arrays mit "echt" fixer Größer und dynamischen Arrays gibt es einen Unterschied und man sollte die Wahl haben, was man braucht.

    Richtig,
    Unterschiedliches verhalten sollte aber auch unterschiedliche Implementationen/Klassen zur Folge haben ^^
    In meiner Welt würde ich da echt ned lange drüber nachdenken, Ob die gemeinsamkeiten es Wert sind, 2 Klassen miteinander zu verheiraten, die eigentlich ned wirklich zusammenpassen. Das führt fast immer zu ...... Design, wenn die DInge Komplexer werden.

    Das verhalten der beiden Typen wird beim "optimieren" vielleicht noch viel weiter auseinander laufen, spätestens wenn auf die Idee kommst, das arrays fixer größe die nicht sonderlich groß sind, besser aufm stack aufgehoben sind als auf dem heap ...

    Ciao ...



  • Ist doch ein Array zur Übung. Darum die Frage, wie man es macht, und nicht in erster Linie, ob.. (warum, bzw warum nicht ist natürlich schon interessant).
    Auf die Frage, was passieren soll, wenn man ungewollt die Größe ändert, würde ich mal ganz einfach "undefiniertes Verhalten" anworten.

    Ich hab noch eine: Ein Templateparameter der angibt ob das Array Fixed oder Resizable ist. Bei dem Fixed Size Array dann die resize Funktion mit SFINAE deaktivieren.

    Also wenn ich jetzt ein internes Array nicht auf dem Heap, sondern auf dem Stack ablegen möchte, dann sind Templates doch die einzige Mäglichkeit, oder?!
    Denn:

    int p;
    int array[p]; //geht
    
    struct c
    {
       int array[q]; //geht nicht ??
       c(int p) : ..?..
       {
       }
    }
    

    Bei dem Fixed Size Array dann die resize Funktion mit SFINAE deaktivieren.

    Naja was ich mich jetzt aber frage: WTF?
    Ich habe mal versucht mir das ohne Nervenzusammenbruch anzusehen... Mit Template-Ellipsen und typedefs habe ich aber bislang wenig bis garnicht gearbeitet.
    Gerade die Tricks mit typedefs und usings sind mir nicht geläufig.. oder es gibt garkeine.;)
    Wie sähe denn diese SFINAE-Deaktivierungs-Geschichte als (Pseudo-)Code aus???

    ..Bei dem was ich so gefunden habe, werden z.B. Template-Funktionen ohne Körper angeboten, und der Kompiler freut sich trotzdem. Das verstehe ich schon mal garnicht. Auch wenn nachher nur der Rückgabetyp auf seine Länge überprüft wird (wozu es ja keinen Funktionskörper braucht), könnte es doch sein, dass in der Funktion z.B. eine globale Variable verändert wird...


  • Mod

    ULong schrieb:

    Ist doch ein Array zur Übung. Darum die Frage, wie man es macht, und nicht in erster Linie, ob.. (warum, bzw warum nicht ist natürlich schon interessant).
    Auf die Frage, was passieren soll, wenn man ungewollt die Größe ändert, würde ich mal ganz einfach "undefiniertes Verhalten" anworten.

    Dann ist es doch einfach:

    typedef dynamic_array fixed_array;
    

    Wenn man dessen Größe ändert, wird die Größe, anders als vom Benutzer erwartet, korrekt geändert.

    (Oder anders gesagt: Du weißt wohl selber nicht, was du willst. Dann kann man dir auch nicht helfen)



  • Oder anders gesagt: Du weißt wohl selber nicht, was du willst. Dann kann man dir auch nicht helfen

    Ach das ist doch Blödsinn. Oder anders gesagt: Ich weiß, dass ich nicht das will was du Hilfe nennst.

    Ist doch klar, dass man undefiniertes Verhalten vermeiden möchte. D.h. wenn ich nicht möchte, dass ein Array seine Größe ändert, dann soll daraus nicht folgen, dass ich die resize() nicht aufrufen darf/sollte, sondern, dass ich sie garnicht aufrufen kann, bzw. ein Aufruf keine Auswirkungen hat.


Log in to reply