von std::vector erben??



  • Artchi schrieb:

    Bademeister schrieb:

    Artchi! dein Code funktioniert nicht!

    Den Template-Parameter wirst du ja wohl noch selber setzen können, oder? 🙄

    Ja aber auch dann geht es nicht.



  • error C2873: 'size' : symbol cannot be used in a using-declaration
    error C2873: 'push_back' : symbol cannot be used in a using-declaration
    


  • Ohne code natürlich sehr aussagekräftig...
    Ich hab private-Vererbung in letzter Zeit auch des öfteren gebraucht

    typedef  std::vector< std::pair<Value,Value> > SolveContainer;
    class SolveModule : public Module , private  SolveContainer {
    
            public:
            using  SolveContainer::operator[];
            using  SolveContainer::size;
            using  SolveContainer::push_back;
    ...
    

    Schreibe deine Klasse analog dazu, dann sollte es gehen.



  • Ja nur weil ichs public nich erben kann wirds im private nicht mehr Sinn machen 😉

    Mit dem virtual verhält es sich doch so, dass der Destruktor bzw. Methoden, die durch eine Subklasse neu implementiert wurde, in jedem Fall augerufen wird.

    Unabhängig von einem Upcast.

    Wurde diese Klasse jedoch nicht ge"upcasted" so macht es doch garkeinen Unterschied ob virtual oder nicht, da das Objekt die Informationen über sich selbst ja kennt.

    Beim erstellen der Subklasse wird erst der Konstruktor der Basisklasse aufgerufen um das Objekt zu erzeugen, danach der eigene. Beim Zerstören des Objektes wird erst der eigene Destruktor aufgerufen und erst dann die aller Superklassen.

    Also warum laufe ich in Probleme wenn ich nie eine Zweideutigkeit (vorallem nicht in dem kleinen Beispiel) provoziere?

    Versteht mich bitte nicht falsch, ich will diese Lösung nicht auf Teufel komm raus durchsetzen. Aber ich würde schon gerne wissen, warum ich es anders machen sollte weil sich das nicht mit der Theorie (zumindest mit meiner ;)) deckt.



  • jghj schrieb:

    Ich möchte halt einfach den vector um ein paar für mich brauchbare Methoden ergänzen.

    Gibt es einen bestimmten Grund warum du auf Teufel komm raus eine Monsterklasse basteln willst, anstelle der offensichtlichen Variante:

    // arr.hpp
    typedef std::vector<char*> arr_t;
    
    void foo( arr_t const& self );
    void bar( arr_t&       self, /*...*/ );
    // ...
    


  • Bademeister schrieb:

    error C2873: 'size' : symbol cannot be used in a using-declaration
    error C2873: 'push_back' : symbol cannot be used in a using-declaration
    

    Sorry, war halt Pseudocode (genauso wie das fehlende Template), habe den Namensraum vergessen.



  • Ich will keine Monsterklasse bauen.

    Und ich denke, dass das Objektorientierte design schon seine Daseinsberechtigung hat. Auch wenn nicht möchte ich es in diesem realisieren und meine eigenen Prozeduren als Methoden und nicht als (globale) Funktionen realisieren.



  • jghj schrieb:

    Ja nur weil ichs public nich erben kann wirds im private nicht mehr Sinn machen 😉

    Es hat keiner gesagt, das es eine Vererbung ist. Es ist eine Lösungsvorschlag, den du anscheinend nicht akzeptieren willst. Mehr können wir aber auch nicht für dich tun.

    jghj schrieb:

    Beim erstellen der Subklasse wird erst der Konstruktor der Basisklasse aufgerufen um das Objekt zu erzeugen, danach der eigene. Beim Zerstören des Objektes wird erst der eigene Destruktor aufgerufen und erst dann die aller Superklassen.

    Also warum laufe ich in Probleme wenn ich nie eine Zweideutigkeit (vorallem nicht in dem kleinen Beispiel) provoziere?

    Versteht mich bitte nicht falsch, ich will diese Lösung nicht auf Teufel komm raus durchsetzen. Aber ich würde schon gerne wissen, warum ich es anders machen sollte weil sich das nicht mit der Theorie (zumindest mit meiner ;)) deckt.

    Hem, das Problem ist, das du der Definition ausweichen und nicht akzeptieren willst. Weißt du was du willst? Du willst eine Container-Klasse spezialisieren, obwohl das mit eben DIESEN Container-Klassen nicht möglich ist. Punkt. Warum ist die Banane krumm? Du wirst keine gerade Banane finden, nur weil dir die krummen nicht fallen. Eine Banane ist per Definition krumm. Punkt!

    Wenn du von vector erbst, wird dessen Dtor nicht immer aufgerufen und somit der Vector nicht korrekt aufgeräumt. Das wirst auch du nicht ändern können. Man kann jetzt fragen, warum Vector keinen virtuellen Dtor hat. Die Frage ist berechtigt, genauso wie mit der Banane. Aber nur wegen der Frage, wird sich die Definition nicht ändern.

    Wenn du Vererbbare Container haben willst, mußt du sie selber (neu) definieren oder im Netz nach entsprechenden suchen.



  • jghj schrieb:

    Ich will keine Monsterklasse bauen.

    Und ich denke, dass das Objektorientierte design schon seine Daseinsberechtigung hat. Auch wenn nicht möchte ich es in diesem realisieren und meine eigenen Prozeduren als Methoden und nicht als (globale) Funktionen realisieren.

    Die Standard-Bibliothek ist ja auch nicht komplett OO. ⚠ C++ ist eine Multiparadigmen-Sprache, und genau das gleiche spiegelt sich in der Stdlib wieder. Viele Typen (wie die Container oder Strings) machen sich lediglich die Möglichkeit des Datenverstecken zu nutze. Das es keine Vererbung gibt, kommt durch die Templates, die das ausgleichen. Und da spielen sicherlich Performance-Gründe eine wichtige Rolle! Es ist ein Paradigma das nunmal gewählt wurde und den C++-Standard ausmacht. Wenns einem nicht gefällt, kann man eine andere Library benutzen.

    Es gibt aber auch Std-Typen (wie die Streams) die vom kompletten OOD Gebrauch machen. Da wird sogar Mehrfachvererbung (iostream) eingesetzt, da hast du sogar das Extrem-OOD! Das ist ein anderes Paradigma, das auch in der Std-Lib existiert.

    Wenn man die Std-Lib benutzt, muß man sich auf diese Paradigmen und somit Design-Entscheidungen einlassen. Und wenn man Vector nicht korrekt vererben kann, dann muß man diese Design-Entscheidung akzeptieren oder man lässt diese Klassen links liegen.



  • Artchi schrieb:

    jghj schrieb:

    Ja nur weil ichs public nich erben kann wirds im private nicht mehr Sinn machen 😉

    Es hat keiner gesagt, das es eine Vererbung ist. Es ist eine Lösungsvorschlag, den du anscheinend nicht akzeptieren willst. Mehr können wir aber auch nicht für dich tun.

    class myvector : private std::vector
    {
        public:
            using size;
            using push_back;
    };
    

    Dieser code sagt mir, DASS es eine Vererbung ist.

    Es ist ein Lösungsvorschlag, der sagt, mach das Gleiche wie ich eh wollte nur definiere mir eben alles als private. Anschließend schalte ich die gebrauchten Methoden wieder frei für den public-Zugriff.

    Dieses bringt mir ja keinen Vorteil, da es genau das gleiche Vorgehen wie ich es bereits probiert habe widerspiegelt. (Um meine Aussage zu verifizieren habe ichs zusätzlich auch noch ausprobiert; das Praxisbeispiel bestätigt meine These)

    Und wie ich vorher versucht hab zu erklären möchte ich nicht den Standard ändern und will auch nicht unbedingt diese Lösung so durchziehen, da ich über die Komposition eine angebrachte Lösung habe (die mir aber nicht ganz so elegant wie die Vererbung erscheint).

    Die Frage, die für mich interessant ist: WARUM geht das nicht? Welche Codefloskel erlaubt mir die Vererbung, ändert aber die Funktionsweise der Superklasse.

    Nicht zuletzt interessiert mich das, weil es ja für mich selbst evtl auch mal sinnvoll sein kann, eine Klasse zu erstellen von der nicht geerbt werden darf.

    Als Argument fällt für mich jedoch der virtuelle Destruktor heraus, weil der ja bei dem Objekt selbst nicht zum tragen kommt und es schon nach der Initialisierung hängt.

    Dass C++ sehr vielseitig usw. ist und auf Altlasten aufbaut ist mir bewusst, jedoch weiß ich nicht warum ich statt einer Komposition oder anderen OO Vorgehensweisen auf einmal zurück zu C soll und mir Hilfsfunktionen anlegen soll?



  • Naja, private-Vererbung ist eigentlich keine Vererbung sondern eine Komposition.
    D.h. deine Klasse ist nacher kein STL-Container, sondern sie hat einen STL-Container!
    Durch den fehlenden virtuellen Destruktor handelst du dir in diesem Fall nur Probleme ein wenn du die Klasse z.B. über den Zeiger der Basisklasse löschen tust.
    Dann wird eben der falsche Destruktor aufgerufen. Darum vermeide das Problem indem du private-Vererbung benutzt und die Schnittstelle gezielt freigibst.



  • Okay das habe ich mitgenommen.

    Der Wert von size() nach dem Erstellen des Objektes ist aber immernoch sehr hoch und falsch... :|


  • Mod

    jghj schrieb:

    Ein Breakpoint nach beiden Objektinitialisierungen im Debugger mit folgenden Outputs von [Objekt].size();

    ar.size() = 3958981726
    vAr.size() = 0

    Ich hab zwar keine Ahnung, was dein Debugger hier anstellt, aber das Ganze ist ohnehin unsinnig. Die size-Memberfunktion muss in deinem Beispiel gar nicht instantiiert werden - der Versuch sie aufzurufen (ist das überhaupt das, was der Debugger dort tut?) daher sinnfrei. Das Verhalten eines Programms ist nicht für Debuggerausgaben definiert worden - wenn die "Größe" des Vektors gar nicht beobachtbar ist, ist die Analyse von Debuggerausgaben sinnlos, wenn du dich nicht von vornherein auf Compilerinterna festlegen willst.



  • jghj schrieb:

    Dass C++ sehr vielseitig usw. ist und auf Altlasten aufbaut ist mir bewusst, jedoch weiß ich nicht warum ich statt einer Komposition oder anderen OO Vorgehensweisen auf einmal zurück zu C soll und mir Hilfsfunktionen anlegen soll?

    Das ist keine Altlast und das hat *nichts* mit C zu tun. Es ist vielmehr ein anderes Paradigma. OOP ist auch *nicht* das Heilige Gral. Diese Hilfsfunktionen sind klares, elegantes und modernes algorithmenbasiertes Anwendungsdesign.



  • Die Algorithmen lassen sich auf (fast) alle Container anwenden, ohne das es eine Basisklasse geben muß. Das Design ist bewusst so gewählt und ich wette, man würde es heute nochmal so machen. Vielleicht würde es heute Detailsänderungen geben, aber das Paradigma würde heute genauso umgesetzt werden. Man muß das Zeug halt verstehen, dann wird man nicht sagen, das es Altlast ist.



  • camper schrieb:

    jghj schrieb:

    Ein Breakpoint nach beiden Objektinitialisierungen im Debugger mit folgenden Outputs von [Objekt].size();

    ar.size() = 3958981726
    vAr.size() = 0

    Ich hab zwar keine Ahnung, was dein Debugger hier anstellt, aber das Ganze ist ohnehin unsinnig. Die size-Memberfunktion muss in deinem Beispiel gar nicht instantiiert werden - der Versuch sie aufzurufen (ist das überhaupt das, was der Debugger dort tut?) daher sinnfrei. Das Verhalten eines Programms ist nicht für Debuggerausgaben definiert worden - wenn die "Größe" des Vektors gar nicht beobachtbar ist, ist die Analyse von Debuggerausgaben sinnlos, wenn du dich nicht von vornherein auf Compilerinterna festlegen willst.

    Ich bin da jetzt zwar nicht ganz mitgekommen aber habe was entdeckt... man gebe die Rückgabe von size() in printf() und er gibt eine 0 zurück.

    Woa ... und ich habe gerade alles durchgetestet es funktioniert .... dann hab ich einen Programmfehler wohl an einer komplett falschen Stelle gesucht, weil ich über das Debuggerergebnis stutzig geworden bin, welches bei mir noch nie falsch war!

    Wäre garnicht auf die Idee gekommen, dass die Ausgabe eine unterschiedliche sein kann....

    Vielen Dank für die schnelle Unterstützung ... wieder was dazugelernt und 2 Tage durch das Suchen an der falschen Ecke vergeuded 😉

    Wünsch euch noch einen schönen Sonntag.

    mfg jghj



  • Artchi schrieb:

    Die Algorithmen lassen sich auf (fast) alle Container anwenden,...

    Von welchen Algorithmen sprichst du? Weißt du von welchen ich gesprochen habe? Außerdem ist das sowas vom Thema ab...willst du dich jetzt rechtfertigen, warum du meine Frage nicht beantworten konntest indem du dich an irgendwelche Normen festbeißt? Deine letzten Beiträge hatten nichts mehr mit meiner Problemlösung sondern viel mehr mit "ich probiere die Kompetenz der anderen in Frage zu stellen" zu tun, wofür ich dir keinen Grund gegeben habe und das meiner Meinung nach auch nicht Zielführend ist.

    Lies dir mal durch, wie oft du auf meine Fragen geantwortet hast ohne Bezug. Oder schreibe ich so undeutlich, dass man das falsch verstehen muss??

    lg jghj



  • jghj schrieb:

    Oder schreibe ich so undeutlich, dass man das falsch verstehen muss??

    Nein, aber anscheinend schreiben wir so undeutlich, dass Du nicht verstehst.

    Das, was Du vorhast, ist in C++ nicht vorgesehen (und aus guten Gründen). Man macht das in C++ einfach anders. Wir empfehlen Dir daher dringend, es ebenfalls so zu machen, denn alle anderen Lösungen haben nunmal massive Nachteile. Abgesehen davon wurden aber bereits verschiedene Ansätze aufgezeigt, die Dein Problem lösen sollten.

    Also was willst Du?



  • jghj schrieb:

    Ich will keine Monsterklasse bauen.

    Dann habe ich dich wohl missverstanden; ich dachte du wolltest ein Array mit char* -spezifischen Methoden ausstatten.

    jghj schrieb:

    Und ich denke, dass das Objektorientierte design schon seine Daseinsberechtigung hat. Auch wenn nicht möchte ich es in diesem realisieren und meine eigenen Prozeduren als Methoden und nicht als (globale) Funktionen realisieren.

    Wer hier hat denn dem Objektorientiertem Design die Daseinsberechtigung abgesprochen? Wieso meinst du mein Vorschlag sei nicht Objektorientiert? Oder war das OOD schlicht ein Tippfehler und du meinst eigentlich Design rein auf statischen Klassen basierend?

    Wieso nutzt du bei deiner Abneigung gegen Funktionen eigentlich die STL?

    jghj schrieb:

    Dass C++ sehr vielseitig usw. ist und auf Altlasten aufbaut ist mir bewusst, jedoch weiß ich nicht warum ich statt einer Komposition oder anderen OO Vorgehensweisen auf einmal zurück zu C soll und mir Hilfsfunktionen anlegen soll?

    Hm. Dass du den Unterschied zwischen globaler und freier Funktion nicht kennst mag man ja noch durchgehen lassen, aber Funktionen als Altlast zu bezeichnen und sie scheinbar abfällig gemeint generell Hilfsfunktionen zu nennen zeugt nicht wirklich von Klasse.



  • jghj schrieb:

    Artchi schrieb:

    Die Algorithmen lassen sich auf (fast) alle Container anwenden,...

    Von welchen Algorithmen sprichst du?

    1. den Standard-Algorithmen (sort, find, transform u.a.)
    2. jeder fremde Algorithmus der sich an das STL-Paradigma der Std-Lib hält

    jghj schrieb:

    Weißt du von welchen ich gesprochen habe?

    Muß ich nicht wissen, weil es irrelevant ist, wenn ein Algo nach STL-Paradigma implementiert wurde.

    jghj schrieb:

    willst du dich jetzt rechtfertigen, warum du meine Frage nicht beantworten konntest indem du dich an irgendwelche Normen festbeißt? Deine letzten Beiträge hatten nichts mehr mit meiner Problemlösung sondern viel mehr mit "ich probiere die Kompetenz der anderen in Frage zu stellen" zu tun, wofür ich dir keinen Grund gegeben habe und das meiner Meinung nach auch nicht Zielführend ist.

    Nach drei Seiten hast du den Fehler bei dir gefunden, obwohl wir dir sehr früh korrekte Antworten lieferten. Ich habe sogar versucht zu erklären, warum das so und nicht anders ist. Nur werde ich keine umfassende Std-Lib-Aufklärung leisten, die in jedem gescheiten C++-Buch oder -Tutorial erklärt wird. Oder hast du keine C++-Literatur?

    Weiterhin habe ich trotzdem sehr wohl Stichworte geliefert, die den Grund dieses Paradigmas nennen. Wenn du dir meine Beiträge nochmal aufmerksam durchliest, wirst du Begriffe wie Templates und Performance vorfinden, die nicht unbedeutend sind (besonders letzteres ist wichtig). Konrad hat auch noch zum Schluss den "algorithmenbasiertes Anwendungsdesign" nachgeliefert, was es nochmal auf den Punkt bringt.


Anmelden zum Antworten