eigener klassentyp im vector



  • camper schrieb:

    Z2 schrieb:

    selbst elementare Konstrukte wie new können werfen

    können, nicht werden oder müssen. Wenn die Umgebungsparameter hinreichend bestimmt sind, kann man das aber möglicherweise ausschließen. Schließlich müssen wir Korrektheit nicht unbedingt generell abstrakt feststellen, sondern können uns auch mit einer konkreten Implementation und Umgebung zufrieden geben.

    push_back ist doch dann ein idealer Kandidat für eine Exception, da vielleicht Speicher allokiert werden muss...


  • Mod

    rüdiger schrieb:

    camper schrieb:

    Z2 schrieb:

    selbst elementare Konstrukte wie new können werfen

    können, nicht werden oder müssen. Wenn die Umgebungsparameter hinreichend bestimmt sind, kann man das aber möglicherweise ausschließen. Schließlich müssen wir Korrektheit nicht unbedingt generell abstrakt feststellen, sondern können uns auch mit einer konkreten Implementation und Umgebung zufrieden geben.

    push_back ist doch dann ein idealer Kandidat für eine Exception, da vielleicht Speicher allokiert werden muss...

    richtig, aber vielleicht garantiert die umgebung ja, dass das nicht passiert.



  • hallo danke für die antworten,

    mich interessiert sehr die erste antwort.
    ich möchte in dem vector aber immer verschiedene objekte drin haben.

    der fall sieht so aus. klasse a und b waren nur pseudonamen. ich habe mehrere clienten die sich per socketprogrammierung an einem server anmelden. wenn der server den clienten dann akzeptiert soll der passende socket im vector gehaslten werden, so das der server über den vector mit allen clienten kommunizieren kann.

    geht das dann so das dann so wie in der ersten antwort? kanns grade nicht ausprobieren weil ich das für einen nebenjob machen muss. und da bin ich erst morgen abend wieder.

    wann muss ich das delete benutzen? dann wenn der client nicht mehr da ist? und wie verwende ich das delete richtig?

    mfg
    vielen dank



  • ein zusatz noch,

    wenn ich ein objekt dem vektor hizufüge und die methode verlassen wird in dem das objekt deklariert wurde. ist es dann noch im vector? oder gibt es das objekt dann nicht mehr weil die methode verlassen wurde??



  • Der vector<> speichert eine Kopie des Objekts, also überlebt es dort drin das Ende deiner Methode.

    Aber wenn es dir um Polymorphie geht, kommst du um einen vector<basis*> (bzw. boost::ptr_vector) wohl nicht herum. Das delete wird dann in dem Moment nötig, bevor du den letzten Zeiger auf das Objekt verlierst (um bei sowas den Überblick zu behalten, helfen Smart-Pointer weiter ;)).



  • Z2 schrieb:

    ...irgendwie habe ich das Gefühl ich wiederhole mich in letzter Zeit ziemlich viel...

    Schau an, da sind wir schon 2. 😃

    Wer hat hier eigentlich nach exception safety gefragt ?
    Poste mal Deinen Code, dann werde ich Dir zeigen, warum der nicht threadsafe ist.
    Oder den threadsafen, der aber nicht performanceoptimiert ist.
    Oder den performanceoptimierten, der aber schwer erweiterbar ist.
    Oder den leicht erweiterbaren, der ....
    Für all diese edlen Zielsetzungen bietet C++ Konstrukte an, um sie abzubilden - trotzdem gehören sie nicht automatisch zur "Korrektheit".

    Eine Kunst beim Programmieren ist, genau die Anforderung abzubilden.

    ... und bei einem simplen "einmal-durchlauf-Programm" auf einem modernen Betriebssystem, spricht nichts dagegen, nach einer Ausnahme den Speicher vom OS aufräumen zu lassen.

    Ich habe den Eindruck, Du hast für Dich gerade entdeckt, dass exception-safety gerade gaaaanz sexy ist und verpulst das jetzt bei jeder Gelegenheit jedem, der es hören will ... und auch allen Anderen. 😉

    Auch hier nochmal: Möchtest Du einem Einsteiger exception-safety erklären (wogegen ich gar nichts habe), dann tue es auch ... aber dann auch gründlich Weiß der Kollege, was exceptions sind, wann man sie wirft, wie man sie fängt, wann stack-unwinding passiert, was exc.-spec. sind (und was nicht), welche Anforderungen man an exception-safety stellen kann (try catch allein reicht nicht !), .... ?
    Wenn Du so viel Spaß an dem Thema hast: schreib' doch mal einen schönen Artikel dazu (vielleicht in die FAQ ?) und verweise einfach jeden Noob, der mit Zeigern arbeiten will darauf. 👍

    Gruß,

    Simon2.



  • @CStoll

    danke, aber was meinste mit polymorphy? sprichst du hier von mehrfachvererbung?
    oder meinste das ich verschiedene Objekte haben will? wahrscheinlich das letztere,
    ich habe c++Referenz das Buch und da guckt ich heute mal nach ob was über diesen Vector Typ steht, aber ich glaube mich zu errinern das da nichts steht , du meinst ich komme daran nicht herum, kannst mir mal das prinzip erklären wo der unterschied zu dem ist wie ich das gemacht habe? oder einen kleinen code zeigen der verschieden objekte in zb. einer for schleife in einem vector ablegt?

    in Java geht das ganz einfach, das ist da selbstverständlich mit dem new operator super easy, aber hier fehlt mir der zusammenhang ein bischen.

    in java ungefähr so

    for (int i=0;i<5;i++){
    A a=new a();   
    vectorB.add(a);
    }
    

    ich glaub der befehl heisst add oder so naja aber so ungefähr funzt es.alle objekte sind verschieden.
    will das selbe jetzt nur
    für c++.

    mfg



  • newly schrieb:

    @CStoll

    danke, aber was meinste mit polymorphy? sprichst du hier von mehrfachvererbung?
    oder meinste das ich verschiedene Objekte haben will? wahrscheinlich das letztere,

    Polymorphier bedeutet, daß erst zur Laufzeit der tatsächliche Typ feststeht (du also verschieden Typen gemeinsam verarbeiten kannst).

    in Java geht das ganz einfach, das ist da selbstverständlich mit dem new operator super easy, aber hier fehlt mir der zusammenhang ein bischen.

    In Java arbeitest du auch (fast) nur mit Pointern - und mußt dich nicht weiter darum kümmern, was hinter den Kulissen mit ihnen passiert (Stichwort: Garbage Collector). In C++ verwendet man Pointer erst, wenn man sie unbedingt braucht (und dann muß man genau darauf achten, wer wann den Pointer wieder freigeben darf).

    In C++ sieht dein Code etwa so aus:

    for(int i=0;i<5;++i)
    {
      A a;//ohne 'new' - das Objekt wird direkt auf dem Stack angelegt
      ... a mit Werten füllen
      vectorB.push_back(a);
    }
    

    (push_back() speichert eine Kopie des übergebenen Objekts, also brauchst du dich nicht darum kümmern, daß a am Ende des Schleifendurchlaufs entsorgt und in der nächsten Runde wiederverwendet wird)



  • Na, dann wollen wir mal: 😉

    camper schrieb:

    rüdiger schrieb:

    camper schrieb:

    Z2 schrieb:

    selbst elementare Konstrukte wie new können werfen

    können, nicht werden oder müssen. Wenn die Umgebungsparameter hinreichend bestimmt sind, kann man das aber möglicherweise ausschließen. Schließlich müssen wir Korrektheit nicht unbedingt generell abstrakt feststellen, sondern können uns auch mit einer konkreten Implementation und Umgebung zufrieden geben.

    push_back ist doch dann ein idealer Kandidat für eine Exception, da vielleicht Speicher allokiert werden muss...

    richtig, aber vielleicht garantiert die umgebung ja, dass das nicht passiert.

    vielleicht, vielleicht auch nicht. Wer kann das schon sagen, ohne nähere Details zu kennen? new war ja nun nur als Beispiel gedacht. Letztlich kann in C++ doch so ziemlich alles werfen. Nehmen wir mal an, man würde Zeiger auf Objekte abgeleiteter Klassen in den Vector legen (ein wesentlicher Grund Pointer zu benutzen). Dieses Konzept ist erweiterbar, d.h. es können jederzeit neue Klassen hinzukommen, die wohlmöglich nicht der Kontrolle des ursprünglichen Autors unterstehen. Eine solche Klasse könnte irgendwo eine Exception werfen, selbst wenn die urspürnglichen Klassen das nicht tun.

    Ok, ich weiß, das war nicht gefragt. Ich weiß auch, das diese Situation nicht zwangsläufig auftreten muß (man könnte zum Beispiel in die Dokumentation der ursprünglichen Klassen schreiben, daß sie nciht werfen dürfen). Aber das wissen wir nicht, weil wir nur dieses winzige Code-Stück gesehen haben.

    Daher bin ich der Meinung, daß man, wenn möglich, eine Antwort geben sollte, die Allgemeingültigkeit besitzt, d.h. für alle möglichen Situationen und Implementierungen der relevanten Klassen gilt.

    Simon2 schrieb:

    Oder den threadsafen, der aber nicht performanceoptimiert ist.
    Oder den performanceoptimierten, der aber schwer erweiterbar ist.

    Was bitte hat Performance mit Korrektheit zu tun?

    Simon2 schrieb:

    Auch hier nochmal: Möchtest Du einem Einsteiger exception-safety erklären (wogegen ich gar nichts habe), dann tue es auch

    Nein, möchte ich eigentlich nicht. Ich glaube es nicht, daß es eine gute Idee ist, einen Einsteiger zu früh mit zuvielen komplexen Aspekten der Sprache zu belasten. Aber ich bin auch der Meinung, daß man einem Einsteiger, wenn man die Wahl zwischen einer Exception-sicheren Methode und einer nicht Exception-sicheren Methode hat, die Exception-sichere Methode an die Hand geben sollte (nebenbei bemerkt, die SmartPointer haben an dieser Stelle ja auch noch andere Vorteile als nur die Exception-Sicherheit).

    Simon2 schrieb:

    .. und bei einem simplen "einmal-durchlauf-Programm" auf einem modernen Betriebssystem, spricht nichts dagegen, nach einer Ausnahme den Speicher vom OS aufräumen zu lassen.

    Das sehe ich etwas anders, aber meinetwegen (müssen das Thema ja nicht totreden). Das ist eigentlich auch gar nicht mein Punkt. Aber:

    - was passiert, wenn im Destruktor des "leakenden" Objekts noch andere System-Resourcen freigegeben werden? System-Resourcen, die weitaus beschränkter sind als Speicher und wo bei einem einmaligen Leak bereits die verfügbaren Resourcen erschöpft sind?

    - was passiert, wenn es kein simples "einmal-durchlauf-Programm" ist?

    Wir wissen schließlich nicht, was der Fragesteller da gerade schreibt (auch wenn ein "einmal-durchlauf-Programm" schon wahrscheinlicher ist). Ist es wirklich klug ihm jetzt einen Code an die Hand zu geben, bei dem er später im Verlauf seines Lernprozesses feststellt, daß der es in vielen Situationen gar nicht tut? Da geben wir ihm doch lieber gleich jetzt die SmartPointer (auf Exception-Sicherheit muß man dabei ja nicht herumreiten).



  • Performancetechnisch wäre die Reihenfolge wohl besser.

    for(int i=0;i<5;++i)
    {
      vectorB.push_back(A()); //ohne 'new' - das Objekt wird direkt im vector auf dem Stack angelegt
    //  ... a mit Werten füllen über
     vectorB.back();  
    }
    


  • newly schrieb:

    ...
    in java ungefähr so

    for (int i=0;i<5;i++){
    A a=new a();   
    vectorB.add(a);
    }
    

    ...alle objekte sind verschieden.
    ...

    ... instantiieren aber alle dieselbe Klasse. Ist es wirklich das, was Du willst (unterschiedliche Objektidentitäten aber identische Objektklasse) ?
    Dann hat das nichts mit Polymorphie zu tun.
    Die kommt erst ins Spiel, wenn Du mit Objekten unterschiedlichr Klassen (also z.B. A und 😎 arbeiten willst. Aber das ist in C++ eigentlich nicht anders als in Java (außer, dass vector typsicher(er) ist, d.h. Du kannst nicht beliebige Objekte reinpacken).

    Gruß,

    Simon2.



  • Z2 schrieb:

    ...Was bitte hat Performance mit Korrektheit zu tun?...

    Die Antwort gibst Du selbst:

    Z2 schrieb:

    ...Daher bin ich der Meinung, daß man, wenn möglich, eine Antwort geben sollte, die Allgemeingültigkeit besitzt, d.h. für alle möglichen Situationen und Implementierungen der relevanten Klassen gilt....

    Mit dem Ansatz musst Du Dich auch mit Threadsafety, Performance, Portabilität, Erweiterbarkeit, ... auseinandersetzen, weil alle diese Aspekte für "... alle möglichen Situationen und Implementierungen ..." relevant sein können.

    Z2 schrieb:

    ...
    Aber ich bin auch der Meinung, daß man einem Einsteiger, wenn man die Wahl zwischen einer Exception-sicheren Methode und einer nicht Exception-sicheren Methode hat, die Exception-sichere Methode an die Hand geben sollte ...

    Welche Klasse der Exceptionsicherheit meinst Du (basic, no-throw oder strong guarantee) ?

    Z2 schrieb:

    ...

    Simon2 schrieb:

    .. und bei einem simplen "einmal-durchlauf-Programm" auf einem modernen Betriebssystem, spricht nichts dagegen, nach einer Ausnahme den Speicher vom OS aufräumen zu lassen.

    ...
    - was passiert, wenn im Destruktor des "leakenden" Objekts noch andere System-Resourcen freigegeben werden? System-Resourcen, die weitaus beschränkter sind als Speicher und wo bei einem einmaligen Leak bereits die verfügbaren Resourcen erschöpft sind?

    Gibt genug Betriebssyteme, die sich hervorragend darum kümmern.

    Z2 schrieb:

    ...
    - was passiert, wenn es kein simples "einmal-durchlauf-Programm" ist?

    Darüber habe ich keine Aussage getroffen.
    Auf genau Folgendes will ich hinaus:

    Z2 schrieb:

    ...
    Wir wissen schließlich nicht, was der Fragesteller da gerade schreibt

    Eben ... und deswegen ist es falsch, ohne diese Kenntnis von "unkorrektem Code" zu sprechen.

    Z2 schrieb:

    ...
    Ist es wirklich klug ihm jetzt einen Code an die Hand zu geben, bei dem er später im Verlauf seines Lernprozesses feststellt, daß der es in vielen Situationen gar nicht tut?...

    (mal abgesehen davon, dass exception "Ausnahme" heißt und nicht "Regel" 😉 )
    Das ist also eine Frage der Didaktik, zu der Du selbst schreibst:

    Z2 schrieb:

    ...Ich glaube es nicht, daß es eine gute Idee ist, einen Einsteiger zu früh mit zuvielen komplexen Aspekten der Sprache zu belasten....

    Das glaube ich auch.
    Außerdem die Gegenfrage: Ist es wirklich klug, ihm ein Werkzeug in die Hand zu geben, ohne ihm zu erläutern, was es tut und warum/wann/wie man es sinnvoll einsetzt ?
    Ist es klug, ihm eine Antwort zu geben auf eine Frage, die er nicht hatte und auf deren Existenz man ihn bestenfalls mit einem Einzeiler hinweist ?

    Gruß,

    Simon2.



  • Warum man besser SmartPointer als nackte Pointer in einen Vektor legt, kann man sicherlich auch einem Anfänger erklären (z.B.: keine Gefahr das delete zu vergessen; wenn Vector ein Datenmember einer Klasse ist, funktionieren automatiscch generierten Kopier-Konstruktor und Zuweisungs-Funktionen usw.). Auf die Exceptions kann man dann mit einem Satz hinweisen und erklären, daß der Lernende sich jetzt noch nicht darum kümmern muß und ihm weitere Einzelheiten zu diesem Thema zu einem späteren Zeitpunkt begegnen werden. Ich finde das (auch aus didaktischen Gesichtspunkten) durchaus vertretbar.



  • Z2 schrieb:

    Warum man besser SmartPointer als nackte Pointer in einen Vektor legt, kann man sicherlich auch einem Anfänger erklären...

    Dann tu das doch einfach ! 😃

    Am Besten in der FAQ ... da ist es besser aufgehoben, als jedesmal, wenn ein Anfänger nach new/delete fragt, es "nebenbei" neu zu tun.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    newly schrieb:

    ...
    in java ungefähr so

    for (int i=0;i<5;i++){
    A a=new a();   
    vectorB.add(a);
    }
    

    ...alle objekte sind verschieden.
    ...

    ... instantiieren aber alle dieselbe Klasse. Ist es wirklich das, was Du willst (unterschiedliche Objektidentitäten aber identische Objektklasse) ?
    Dann hat das nichts mit Polymorphie zu tun.
    Die kommt erst ins Spiel, wenn Du mit Objekten unterschiedlichr Klassen (also z.B. A und 😎 arbeiten willst. Aber das ist in C++ eigentlich nicht anders als in Java (außer, dass vector typsicher(er) ist, d.h. Du kannst nicht beliebige Objekte reinpacken).

    Gruß,

    Simon2.

    ja die sind alle vom selben typ, eine klasse abgeleitet von asyncsocket.
    hab mir gedacht
    im vector steht dann

    ---Vector---
    a
    a
    a
    a

    der vector hat 4 elemte.
    jedesmal wenn ein socket eine connect anfrage kriegt soll ein a erzeugt werden und im vector gespeichert werden, so das ich über dieses a mit dem clienten kommunizieren kann.

    wenn ich nur ein globales a habe und ein client connectet sich geht es, aber der zweite client, also ein anderer pc kann keine verbindung mehr aufbauen weil diese socket schon belegt ist ??!!?! so denke ich deswegen möchte ich die im vector ablegen.

    versteht ihr wie ich das meine?
    ich meine so sollte es funktionieren wenn ich das jetzt so mache wie mir hier vorgeschlagen wurde von simon2.
    Vielen Dank nochmal

    oder soll ich nochmal code dazu posten den ich dann natürlich selektiv hiereinsetzen so das ihr nicht zuviel da ist nur das relevante eben.

    mfg



  • CStoll schrieb:

    newly schrieb:

    @CStoll

    danke, aber was meinste mit polymorphy? sprichst du hier von mehrfachvererbung?
    oder meinste das ich verschiedene Objekte haben will? wahrscheinlich das letztere,

    Polymorphier bedeutet, daß erst zur Laufzeit der tatsächliche Typ feststeht (du also verschieden Typen gemeinsam verarbeiten kannst).

    in Java geht das ganz einfach, das ist da selbstverständlich mit dem new operator super easy, aber hier fehlt mir der zusammenhang ein bischen.

    In Java arbeitest du auch (fast) nur mit Pointern - und mußt dich nicht weiter darum kümmern, was hinter den Kulissen mit ihnen passiert (Stichwort: Garbage Collector). In C++ verwendet man Pointer erst, wenn man sie unbedingt braucht (und dann muß man genau darauf achten, wer wann den Pointer wieder freigeben darf).

    In C++ sieht dein Code etwa so aus:

    for(int i=0;i<5;++i)
    {
      A a;//ohne 'new' - das Objekt wird direkt auf dem Stack angelegt
      ... a mit Werten füllen
      vectorB.push_back(a);
    }
    

    (push_back() speichert eine Kopie des übergebenen Objekts, also brauchst du dich nicht darum kümmern, daß a am Ende des Schleifendurchlaufs entsorgt und in der nächsten Runde wiederverwendet wird)

    oh sorry falsches zitat hatte ich eben genommen.
    ich meinte den code von Cstoll
    danke nochmals.



  • newly schrieb:

    ...
    versteht ihr wie ich das meine?
    ich meine so sollte es funktionieren wenn ich das jetzt so mache wie mir hier vorgeschlagen wurde von simon2.
    ...

    sieht OK aus.

    Ich wollte nur sichergehen, dass ich Dich richtig verstanden habe - vA, weil Du im Eröffnungspost noch eine "Klasse B" erwähnst ...

    Aber jetzt ist alles klar.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    newly schrieb:

    ...
    versteht ihr wie ich das meine?
    ich meine so sollte es funktionieren wenn ich das jetzt so mache wie mir hier vorgeschlagen wurde von simon2.
    ...

    sieht OK aus.

    Ich wollte nur sichergehen, dass ich Dich richtig verstanden habe - vA, weil Du im Eröffnungspost noch eine "Klasse B" erwähnst ...

    Aber jetzt ist alles klar.

    Gruß,

    Simon2.

    ja weil in klasse b der vector ist der auf aufnehmen soll, deswegen.
    ps, hier muss ich ja keine speicherfreigabe machen oder? ich meine benutze so dann ja nicht der new operator??!!



  • Z2 schrieb:

    Na, dann wollen wir mal: 😉

    vielleicht, vielleicht auch nicht. Wer kann das schon sagen, ohne nähere Details zu kennen? new war ja nun nur als Beispiel gedacht. Letztlich kann in C++ doch so ziemlich alles werfen. Nehmen wir mal an, man würde Zeiger auf Objekte abgeleiteter Klassen in den Vector legen (ein wesentlicher Grund Pointer zu benutzen). Dieses Konzept ist erweiterbar, d.h. es können jederzeit neue Klassen hinzukommen, die wohlmöglich nicht der Kontrolle des ursprünglichen Autors unterstehen. Eine solche Klasse könnte irgendwo eine Exception werfen, selbst wenn die urspürnglichen Klassen das nicht tun.

    1. wenn new ne exception wirft- was willst du dann machen?
    new exceptions kannste durchrasseln lassen, an dem punkt ist eh alles verloren.
    Vielleicht, wenn du hohe ziele hast, legst du um die main nen try...catch block und schreibst(sofern möglich)nen fehlerlog, aber mehr geht nicht.
    Sicher, manchmal muss man wichtige resourcen freigeben, aber bis man diese resourcen kennt, hat man schon genug über exception sicherheit gelernt, im zweifelsfall wird man bei der lektüre über diese resourcen direkt mit der nase auf das problem gestoßen.
    2. was machst du mit exceptions von Klassen, die du nicht kennst? du kannst ja nichtmal einschätzen, was diese exceptions bedeuten,geschweige denn sinnvoll bearbeiten.
    3. wichtiger als try...catch blöcke ist exception sicherer code. Wenn ich garantieren kann, dass der status meiner Klasse unverändert bleibt, wenn eine methode aus irgendeinem grund ne exception wirft(zb weil ein polymorphes Objekt kaputt ist), ist das viel mehr wert als panisches aufräumen von resourcen. Vorallem, weil der Fehler vielleicht doch korrigiert werden kann.



  • otze spricht einen sehr wichtigen Punkt an, nämlich dass Exception-Behandlung meist nicht auf unterster Ebene im Code geschehen kann. Deshalb ist es mir auch unverständlich, warum man um alle drei Zeilen ein try-catch schreiben soll.


Anmelden zum Antworten