zeigertyp zur laufzeit ändern?



  • Dravere schrieb:

    tenim schrieb:

    wiso wtf? was ist an meinem code falsch?

    Weil es ein äusserst hässliches rumgefrickel ist. Sowas hat man vielleicht in C gemacht, in C++ gibt es dazu andere Möglichkeiten.

    Nicht einmal. In C wäre das rein mit malloc gemacht worden und nicht auch noch mit new ebenfalls.. Ich möchte gar nicht wissen, wo und wie er das wieder freigibt.. 🙄



  • ich hab es jetzt schöner lösen können:

    da meine mir bisher unbekannten klassen alle von einer basisklasse A erben, sind diese ja zuweisungskompatibel, wenn ich bei der vererbung "public" angebe(hatte ich vergessen bzw. bis jetzt nicht gewusst -komme von der java ecke).

    so brauche ich mir jetzt keine sorgen mehr zu machen, ich kann im konstruktor
    einfach schreiben

    inhalt **A;

    und nach dem erzeugen der objekte B,C,D (welche ja von A erben), kann ich die objektreferenzen trotzdem zuweisen, weil halt zuweisungskompatibel.

    inhalt[1]=new B();

    hintergrund:
    ich schreibe einen raumschiffsimulator, der im perryversum angesiedelt ist. 🙂

    es ging im detail darum, das ich eine basisklasse "Energieerzeuger" habe, von der alle "echten" energieerzeuger wie z.b. Fusionsreaktoren oder Schwarzschildgeneratoren abgeleitet sind. die klasse "Energieerzeuger" dient somit nur der bereitstellung von eigenschaften und methoden, die jeder echte
    "Energieerzeuger" hat. die beiden obengenannten "Energieerzeuger" sind aktive, also sie erzeugen selbst energie. ausserdem gibt es eine klasse kraftwerk, welches aus mehreren aktiven Energieerzeugern besteht und selbst passiv ist(weil es ja keine energie aus eigener kraft erzeugt). auch die klasse kraftwerk ist von der basisklasse "Energieerzeuger" abgeleitet, da diese auch diese eigenschaften hat.

    jetzt das problem:
    erst zur laufzeit, also wenn bekannt ist was für ein raumschiff-modell gewählt wurde, kann ich anfangen, mehrere kraftwerk-objekte in dem schiff zu platzieren.
    dabei muss ich im konstruktor des kraftwerks natürlich angeben
    a) welcher typ von energieerzeuger verbaut werden soll und
    b) wieviele davon

    ich habe allerdings schon im konstruktor des kraftwerks eine variable mit dem zukünftigen array von "Energieerzeuger"-objekten angelegt. das kann ich dann später durchiterieren, egal was für ein typ von kindobjekt darin gefunden wird.
    eben:

    Energieerzeuger  **pEnergieerzeuger;
    

    dieses array muss ich dann

    1. initialisieren:

    pEnergieerzeuger=(Energieerzeuger**)malloc(4*cAnzahl);
    

    (da jeder zeiger 4 byte braucht(im 32bit system) reserviere ich 4*anzahl.)

    2. objekte zuweisen:
    (eEt ist ein enum mit den typen der erzeuger, die anderen varianten hab ich noch nicht programmiert)

    for(i=0;i<cAnzahl;i++)
    	{
    		switch (eEt)
    		{
    			case FusionsreaktorTerraTyp1:
    				pEnergieerzeuger[i]=new Fusionsreaktor_Terra_Typ1(i+1);
    				break;
    		}
    	}
    

    3. nutzen des objektes

    pEnergieerzeuger[1]->fahreHoch();
    

    scheint jetzt soweit alles zu klappen.
    🙂

    bin natürlich für elegantere lösungen dankbar.



  • hey mr. "drakon"

    ich habs in meinem letzten post bereits mit malloc gemacht.
    deine überhebliche art kannst du dir sparen. du bist nicht der einzige, der programmieren kann. ich bin bestimmt kein c++ crack, aber ich machs ja erst seit 2 tagen i n c++.

    p.s.

    freigben tue ich das so:

    free(pEnergieerzeuger);



  • tenim schrieb:

    deine überhebliche art kannst du dir sparen. du bist nicht der einzige, der programmieren kann. ich bin bestimmt kein c++ crack, aber ich machs ja erst seit 2 tagen i n c++.

    Das hat mit Überheblichkeit nix zu tun.
    In C++ macht man solche Sachen mit new und delete, egal was du früher gemacht hast. Denn mit new und delete bist du auf der sicheren Seite. Insbesondere wenn deine Klassen mal komplexer werden, oder du die Strukturen verändern willst und dabei ein Objekt mal gerade nicht seine 4 Byte groß ist, dann geht das Gefrickel los. Nimm dir doch einfach die Zeit und lies ein Buch, bevor du dir aus deinem (C-)Hintergrund heraus schlechten Stil angewöhnst.



  • ok, aber ob ich es mit malloc oder new mache ist doch relativ egal da ich in beiden fällen darauf achten muss, die ressourcen manuell wieder freizugeben.
    wenn ich wegen der operandengrösse nicht sicher bin, kann ich ja sizeof() nehmen.

    ich hab ja malloc nicht ohne triftigen gund angewandt. es ging darum, ein array von n objektreferenzen anzulegen, OHNE die objekte selbst alle auf einmal zu instanzieren. wenn du mir erklärst, wie ich das mit "new" hinkriege, bitte.



  • tenim schrieb:

    ich hab ja malloc nicht ohne triftigen gund angewandt. es ging darum, ein array von n objektreferenzen anzulegen, OHNE die objekte selbst alle auf einmal zu instanzieren. wenn du mir erklärst, wie ich das mit "new" hinkriege, bitte.

    Aber du hast ihn ja sofort danach zugewiesen. Da hättest du auch new nehmen können. Und da das ganze Anwendungscode ist, würde ich das auch in einen Smart Pointer packen. Dann hast du die volle flexibiltät und musst dir keine Sorgen um die Speicherverwaltung machen..

    Und wenn es denn wirklich sein muss, dann würde ich auf vorgefertige Funktionalitäten zurückgreifen und mir einen anständigen Wrapper schreiben und nicht einfach drauflos programmieren..
    http://www.cplusplus.com/reference/std/memory/
    http://www.cplusplus.com/reference/std/new/



  • nein, ich erstell jede objektinstanz mit anderen parametern. deshalb kann ich nicht alles in einem rutsch machen.



  • tenim schrieb:

    nein, ich erstell jede objektinstanz mit anderen parametern. deshalb kann ich nicht alles in einem rutsch machen.

    OK. Das sieht man aber in deinem Beispiel nicht..

    Wie auch immer wäre das alleine für mich noch lange kein Grund malloc oder auch nur new zu benutzen. Ich würde vorher einen Standardcontainer nehmen und da die Elemente pushen und das kannst du für jedes Element andere Parameter übergeben.

    Und wenn ich das aus irgendeinem Grund nicht machen kann/will, dann würde ich sogar vorher einfach die Elemente erzeugen (mit dem Standardkonstruktor) und dann über einen setter die Werte setzen.

    Aber wenn du das unbbedingt mit malloc machen willst..



  • tenim schrieb:

    hey mr. "drakon"

    ich habs in meinem letzten post bereits mit malloc gemacht.
    deine überhebliche art kannst du dir sparen. du bist nicht der einzige, der programmieren kann. ich bin bestimmt kein c++ crack, aber ich machs ja erst seit 2 tagen i n c++.

    Du scheinst ja nicht gerade sehr kritikfähig zu sein. Dravere und drakon haben völlig Recht mit ihren Einwänden.

    Wenn du aus C kommst, kannst du innerhalb von 2 Tagen noch kein C++. Die Konzepte sind grundlegend anders, manuelle Speicherverwaltung kann auf ein Minimum reduziert werden. Das heisst, dass du meistens weder mit malloc() noch mit new hantieren musst, sondern fertige Container der STL anwenden kannst.

    Dann hast du

    std::vector<MyClass> Vec;
    Vec.push_back(MyClass(25, "x25-b77", true));
    

    Das ist doch wohl schöner als jegliches Rumgefrickel mit malloc() .

    • Wie willst du mit malloc() Konstruktoren aufrufen, ohne Placement New einzusetzen?
    • Was, wenn du plötzlich ein Element anhängen willst, und der Speicher nicht mehr reserviert ist?
    • Hast du Kopierkonstruktor und Zuweisungsoperatoren überladen oder wenigstens private gemacht?
    • Rufst du vor dem Freigeben mit free() die Destruktoren auf?
    • Hast du eine separate Variable für die Grösse des dynamischen Arrays, die auch ständig aktualisiert wird?
    • Wie willst du mit malloc() effizient debuggen? Bei den STL-Containern erhält man Assertions.
    • Was ist, wenn du plötzlich merkst, dass ein dynamisches Array doch nicht die richtige Datenstruktur ist und statt dessen eine verkettete Liste angebracht wäre?

    Alle diese Probleme hast du mit STL-Containern nicht. Zudem hast du damit sauberen, übersichtlichen und somit gut wartbaren Code. Die Fehleranfälligkeit und allfällige Memory Leaks fallen praktisch weg.



  • nein, ich komme nicht unbedingt aus der c ecke. hab zwar in c einige zeit programmiert, aber mehr mit java(hab ich auch in einem posting geschrieben, liest halt keiner richtig).

    und kritikfähig bin ich schon, das kannst du mir glauben. nur der ton macht die musik und es ist oft wichtiger, wie jemand etwas sangt, als was er sagt.
    und der umgangston war einfach unhöflich. das erkennen viele leute nicht, weil sie einfach zu tief in ihrer materie drin sind und darauf keinen wert legen.

    ich allerdings schon.



  • tenim schrieb:

    nein, ich komme nicht unbedingt aus der c ecke. hab zwar in c einige zeit programmiert, aber mehr mit java(hab ich auch in einem posting geschrieben, liest halt keiner richtig).

    Hm, während des Threadverlaufs hatte ich irgendwie das Gefühl bekommen, du seist aus C. Wie auch immer, malloc() und free() sind C und haben bis auf einige Ausnahmen nichts in C++ zu suchen (nein, dein Fall ist keine solche Ausnahme).

    tenim schrieb:

    und kritikfähig bin ich schon, das kannst du mir glauben. nur der ton macht die musik und es ist oft wichtiger, wie jemand etwas sangt, als was er sagt.
    und der umgangston war einfach unhöflich. das erkennen viele leute nicht, weil sie einfach zu tief in ihrer materie drin sind und darauf keinen wert legen.

    Es wird auch nicht gerade besonders geschätzt, wenn man als Fragesteller nicht auf die Antworten eingeht. Es wurden viele Vorschläge gebracht, aber du scheinst auf deiner Frickellösung zu beharren. Ich hab zum Beispiel in meinem letzten Post auch versucht, dir die Nachteile vom Rumgefrickel aufzuzeigen. Entweder du glaubst mir, oder ignorierst meinen Post weiterhin. Du musst ja schlussendlich wissen, wie du programmierst. Aber ich wünsche dir jetzt schon mal viel Spass beim Debuggen und Warten...



  • tenim schrieb:

    und kritikfähig bin ich schon, das kannst du mir glauben. nur der ton macht die musik und es ist oft wichtiger, wie jemand etwas sangt, als was er sagt.
    und der umgangston war einfach unhöflich. das erkennen viele leute nicht, weil sie einfach zu tief in ihrer materie drin sind und darauf keinen wert legen.

    Wo war jemand unhöflich? - Ist es wegen meinem WTF? - Ich habe wahrscheinlich als einziger gesagt, was er gedacht hat, als er das Konstrukt gesehen hat. Es bringt dir nichts, wenn wir hier sagen: "ja, mach mal.. das geht schon so..". Dann hast du irgendwann mal ein riesen Problem seie es, weil dein Programm aus "unerklärlichen" Gründen abstürtzt, oder weil dein Chef mal auf deinen Programmcode schaut. Und eines kann ich dir garantieren, wenn er so etwas sieht, dann wird er auch so etwas ähnliches, wie WTF sagen..

    Vor allem als Anfänger sollte man sich mal auf die Standardbibliothek verlassen und sich nicht um Speicherverwaltun kümmern müssen. Das kannst du auch mal später noch machen, wenn du mehr Erfahrung hast..


  • Administrator

    @tenim,
    Also zuerst einmal zu malloc . Ich würde in C++ kein malloc benutzen, wenn du nicht ganz genau weisst, was du tust. malloc und new sind intern etwas anders.

    Und zu deinem Problem:
    Ich würde einen EnergieerzeugerManager machen, welcher die Energieerzeuger lädt und verwaltet. Von jedem Energieerzeuger brauchst du ja nur eine Instanz, mehr nicht.
    In deinem Kraftwerk oder Schiff, machst du dann einfach einen std::vector<Energieerzeuger*> . Und dazu eine Funktion, wo du die Dinger hinzufügen kannst. Also nicht per Konstruktor oder so, das hat meiner Meinung im Konstruktor nichts zu suchen.
    Du holst dann beim Manager per ID oder Name den entsprechenden Energieerzeuger und übergibst diesen an das Kraftwerk oder Schiff.

    Im übrigen, würde ich nicht für jeden Energieerzeuger eine eigene Klasse erstellen. Es wäre sinnvoller, wenn du das in den Attributen vom Energieerzeuger speicherst. So kannst du am Ende sogar extern ein XML/Config File zur Verfügung stellen, wo du dann ganz einfach Energieerzeuger ergänzen oder verändern kannst.

    ... nur so Ideen 🙂

    Grüssli



  • ok, danke für die mühe. ich schau mal, wie sich das macht mit std::vector.
    bin halt eher ein pragmatischer programmierer und sehe bisher die vorteile des vectors noch nicht, weil ich ihn halt noch nicht kenne.
    werd mich dann damit mal beschäftigen...

    p.s. ich hab schon ein c++ buch, das ich teilweise nebenbei lese. es ist "die c++ programmiersprache" von stosstrupp 🤡 oder wie der heisst.



  • tenim schrieb:

    von stosstrupp 🤡

    Ohman das ist Top 😃 "stosstrupp" :D:D Nicht schlecht :p 👍



  • Firefighter, hast du jetzt einen Thread, wo du solche Dinge sammelst? 😉



  • tenim schrieb:

    von stosstrupp 🤡

    😃 - Echt Klasse.

    Wäre doch auch ein klasse Name für einen dieser speziellen Filme.. :p



  • Nexus schrieb:

    Firefighter, hast du jetzt einen Thread, wo du solche Dinge sammelst? 😉

    Leider nein, ich hab ja kein Feedback von einem Moderator bekommen. Daher nochmal die Frage an die Mods, kann man eventuell so einen Sammelthread mit allen wunderbaren Sprachlichen Auswüchsen aufmachen und den festpinnen?


  • Administrator

    Ich finde immer noch den FAQ Eintrag auf Stroustrup's Seite so geil:
    http://www.research.att.com/~bs/bs_faq.html#pronounce

    Er scheint noch oft Probleme mit seinem Namen zu haben 😃

    Grüssli



  • ok, nochmal zurück zum thema. ich hab meinen code jetzt auf vector-nutzung umgeschrieben. deshalb muss ich mir nicht mehr um die anzahl der elemente gedanken machen, die in die liste reinkommen weil dynamisch. aber auf die verwendung von "new" kann ich doch trotzdem nicht verzichten, weil ich ja die objektreferenzen irgentwie in den vector bekommen muss.

    std::vector<A*>  liste;
    liste.push_back(new A());
    

    und dann muss ich doch zum schluss wieder erst alle objekte über deren zeiger im vector mit delete freigeben, oder macht das der vector automatisch wenn er selbst zerstört wird?
    meine das so:

    for(i=0;i<liste.size();i++)
        delete liste[i];
    

    ist das nötig?


Anmelden zum Antworten