Ergebnis 1 bis 7 von 7

Thema: Frage zu Union-Einheiten

  1. #1

    Frage zu Union-Einheiten

    Hallöchen,

    ich hätt mal wieder eine Frage, diesmal zur Union in C++. (Dürfte aber in anderen Sprachen ähnlich sein).
    Und zwar habe ich eine Klasse listenelement welche als Attribute Objekte von 3 anderen Klassen haben soll. Etwa so:
    Code:
    class listenelement
    {
        public:         
                        object teil1;
                        object2 teil2;
                        object3 teil3;
    };
    (Attribute sind zum Test beabsichtigt public).

    Ich habe nun mehrere Objekte der Klasse listenelement welche jeweils aber immer nur die Daten eines der 3 Klassen object, object2 und object3 benötigt. Also es kommt nicht vor, dass dieses Objekt vom Typ listenelement den Speicher für teil1 und teil2 oder teil1 und teil3 oder so benötigt. Sondern immer nur entweder teil1, teil2 oder teil3 werden beansprucht.
    Da dachte ich mir, um Speicher zu sparen, packe ich das Ganze in eine Union. Das sähe dann ja so aus:
    Code:
    class listenelement
    {
        public:      union{        
                        object teil1;
                        object2 teil2;
                        object3 teil3;
                        };
    };
    Jedes der Objekte benötigt unterschiedlich Speicher, die Klasse object etwa beinhaltet Attribute mit der Größe von 60 byte, object2 beinhatet 79 byte und object3 130 byte große Attribute. (Alle Werte sind Beispielwerte die aber meinem Programm recht nah' kommen).

    Wie wird jetzt genau der Speicher reserviert? Der reservierte Speicher muss ja irgendwie groß genug sein, dass aus das größte Objekt der Union reinpasst, also 130 byte. Oder kann man Klassen bzw. Objekte garnicht so in Unions packen? Funktioniert das wirklich so zuverlässig, dass es da keine Probleme mit Objekten in Unions gibt, auch wenn die Objekte teils recht komplexe weitere Vererbungen (manchmal mehrfach-vererbungen) von anderen Klassen sind?
    Oder kann man diese Art wahlweisen Zugriff möglicherweise noch ganz anders in der OOP lösen, durch eine Art dynamisch ein Attribut erstellen oder so?

    Wär schön wenn mir da jemand was zu diesen Union-Einheiten sagen könnte.

    EDIT: Wo wir gerade dabei sind, gleich die nächste Frage dazu.
    Mal angenommen, ich möchte dieses objekt jetzt ansprechen, würd ich das ja so tun:

    Code:
    listenelement name;
    name.teil1."attribut"
    Für den Fall, dass dieses Objekt Listenelement die Daten des Objekts "teil2" beinhalten soll, müsste ich es so ansprechen:
    Code:
    listenelement name;
    name.teil2."attribut"
    Nun ist die Frage, wie könnte man es einrichten, dass man die Attribute der Objekte teil1 oder teil2 mit ein und dem selben Aufruf ansprechen kann? Also, dass beide Attribute der Objekte so anzusprechen sind:
    Code:
    listenelement name;
    name.union."attribut" = *sonstwas*
    Union kann da jedes beliebige Wort sein, was auch immer.

    Ich dachte da an pointer, dass man die Adresse des Objekts teil1 oder teil2 in einem Pointer speichert und dann mittels dieses Pointers auf die Attribute von teil1 oder teil2 zugreifen kann:

    Code:
    class listenelement
    {
        public:      union{        
                        object teil1;
                        object2 teil2;
                        object3 teil3;
                        };
     object* pointer;
    };
    //...
    pointer = &teil1;  //<-- Irgendwo folgt dann zuweisung der Adresse, je nach genutztes Element ist es auf teil1, teil2 oder teil3...
    //...
    
    listenelement name;
    name.pointer->"attribut" = *sonstwas*
    Die Problematik hier ist jetzt, dass ich das ich da Probleme mit den Typen der Pointer bekomme. Das hier: "pointer = &teil1;" kann ich nur so schreiben, wenn ich auf teil2 zeigen will, geht dies nicht, da teil2 vom Typ object2 ist. Und den Pointer hab ich innerhalb der Klasse listenelement ja als pointer des typs object erstellt.
    Wie ließe sich das machen, dass ich einen Pointer erstellen kann, der auf jedes der drei Elemente zeigen kann?
    Kann man den Pointer irgendwie dynamisch je nach Typ des Objects casten lassen?
    Dass, wenn er auf teil1 zeigt, er den Typ object annimmt, bei teil2 den Typ object2 und bei teil3 den Typ object3?

    Hach, das klingt jetzt sicher alles recht verwirrent. Hat's vielleicht trotzdem jemand verstanden und kann mir da helfen? Ich will doch nur dynamisch auf einen der 3 objecte zugreifen können mit dem selben Aufruf (mittels pointer oder sonstwie) und diese 3 Elemente sollen sich den Speicher teilen, da immer nur eines in Benutzung ist.


    mfg.

    Ynnus aka Sunny

    Geändert von Ynnus (16.05.2005 um 01:33 Uhr)

  2. #2
    Zum ersten Problem hab ich leider keine Antwort. Würde mich auch interessieren. Zum zweiten schon:
    Code:
    union {
    object1 teil1;
    object2 teil2;
    object3 teil3;
    } alleTeile;
    
    // Ich weiß nicht obs wirklich geht und ob unions nicht nur mit Primitiven gehen.
    // Zugriff geht (theoretisch) über
    
    alleTeile.attribut;
    
    // Wobei ich gerade daran Zweifel, dass das wirklich geht. Denn der Compiler muss ja den Typ des Objekts wissen um das Attribut zu bekommen. Mmh. Vielleicht auch..
    
    ((object2)alleTeile).attributVonObject2;
    Da fällt mir was anderes ein, das auf jeden fall funktionieren sollte:
    Code:
    union {
    object1* pTeil1;
    object2* pTeil2;
    object3* pTeil3;
    } alleTeile;
    
    // Zugriff:
    ((object2*)alleTeile)->attributVon2;
    Da musst du dich halt selber um den Speicher kümmern.

  3. #3
    Ich greif bis jetzt so auf einzelne Elemente zu:

    "unit.current->data.set_selection(false)"

    Also schon recht viel Schreibarbeit und es sollte nicht mehr werden.
    Data ist in diesem Fall eines der drei objecte teil1, teil2 oder teil3.

    Und dieses Listenelement wird bereits dynamisch angelegt und beinhaltet dann das Object data, weshalb ich das nur ungern auch wieder dynamisch zuweisen würde. Dann hätt ich da doppelte Speicherverwaltung zu berücksichtigen. Denn der pointer current zeigt bereits auf ein dynamisch erstelltes Object des Typs listenelement.

    Es sollte also möglichst kein Pointer auf Speicher sein sondern tatsächlich die Byte für dasjeweilige Object beinhalten.

    Zitat Zitat
    union {
    object1 teil1;
    object2 teil2;
    object3 teil3;
    } alleTeile;

    // Ich weiß nicht obs wirklich geht und ob unions nicht nur mit Primitiven gehen.
    // Zugriff geht (theoretisch) über

    alleTeile.attribut;

    // Wobei ich gerade daran Zweifel, dass das wirklich geht. Denn der Compiler muss ja den Typ des Objekts wissen um das Attribut zu bekommen. Mmh. Vielleicht auch..

    ((object2)alleTeile).attributVonObject2;
    Und was meine gestrigen Tests mit den Unions anbelangt, sieht der Zugriff so aus:
    alleTeile.teil1.attribut;
    oder
    alleTeile.teil2.attribut;
    oder
    alleTeile.teil3.attribut;

    Das ist auch genau mein Problem. Denn die Benutzung der drei Teile soll so dynamisch erfolgen, dass ich nicht genau vorher weiß, welches der drei objecte benutzt werden soll. Also stört es nur, dass ich vorher genau den namen des Objects mit angeben muss.
    Eine Ansprache wie "alleTeile.attribut;" wäre viel einfacher.
    Und wenn ich das umgehen will, indem ich einen Pointer auf teil1, teil2 oder teil3 richte und dann im Aufruf nutze, sieht das zwar so aus:
    alleTeile.pointer->attribut;
    und im ersten Moment ist das Problem damit gelöst, ein Name zum Aufrufen des entsprechenden Elements im darauf gezeigten Object, allerdings bekomm ich da Probleme mit dem Typ des Pointers. Denn ich muss diesem Pointer ja einen Typ geben, entweder object1, object2 oder object3. Und dementsprechend kann er dann nur auf dieses Object zeigen. Daher auch die Frage, ob sich der Pointer irgendwie dynamisch nach dem Typ anpassen kann, auf den er zeigt.

    Wenn sich das nicht machen lässt, müsste ich eventuell in einen extra variablen eine Zahl für den Typen vereinbaren und dann per if die Zahl auswerten und manuell in den Typ casten, auf den gezeigt wird, teil1, teil2 oder teil3. Aber sowas möcht ich ja, wenn möglich, vermeiden und möglichst dynamisch bleiben.

  4. #4
    Also in Java wär das gar kein Problem, wenn die alle von einer gemeinsamen Basisklasse erben (Im Zweifelsfall Object) Ich denk mal, in C++ sollte das auch gehen. Einfach ein Pointer auf ein Objekt der Basisklasse.

  5. #5
    Zitat Zitat von DFYX
    Also in Java wär das gar kein Problem, wenn die alle von einer gemeinsamen Basisklasse erben (Im Zweifelsfall Object) Ich denk mal, in C++ sollte das auch gehen. Einfach ein Pointer auf ein Objekt der Basisklasse.
    Selbst wenn die eine Basisklasse hätten von der alle drei Teile erben, dazu kommen ja noch andere Attribute welche einzigartig in den jeweiligen drei Objecten teil1, teil2 und teil3 sind. Und diese Attribute kennt die Basisklasse nicht. Von daher kann ich mit dem Pointer des Typs der Basisklasse auch nicht alle Object-Attribute ansprechen.

  6. #6
    Wenn ich jetzt nicht alles über OOP vergessen habe, kannst du das doch. In Delphi ging so etwas mittels "as", ich bin sicher in C++ gibt es etwas vergleichbares. (explizites casten?)

    Wenn mich nicht alles täuscht ist ja gerade das die Polymorphie (eine Variable für mehrere verschiedene Klassen), eine der wichtigen Eigenschaften von OOP.

    Andererseits ist die Frage ob dir das soviel an Ersparniss von Schreibarbeit bringt.
    Wie wäre es denn, wenn du den Zugriff rein über Methoden machst, die in der Basisklasse vorhanden sind und von object1-3 überschrieben worden sind? Zur Not machst du dann halt einige leere Methoden bei den kleineren Objekten.
    Du hast eine einzige Aufrufart, und dich braucht es nicht kümmern, welches Objekt jetzt gerade durch den Pointer angesprochen wird, das übernimmt dann alles der Compiler..

    (So.. schlagt mich wenn ich hier totalen Bockmist erzählt habe..)

  7. #7
    Das was Magor geschrieben hat ist die methode, die ich auch empfohlen haette ...

    zur Not mach es mit Mehrfachvererbung ...

    Nehmen wir an, obj1, obj2 und obj3 sind von base abgeleitet. Dann kannst du einer Variablen vom Typ base auch ein Objekt vom Typ obj1, obj2 oder obj3 zuweisen. (Vorsicht Copyoperator), was aber ueber Zeiger oder Referenzen viel eindeutiger ist.

    Mit Unions zu arbeiten war schon unter C nicht ganz ohne und eine haeufige Fehlerquelle. Unter C++ gerade bei Operatoren wuerde ich dir dringend abraten, da es teilweise von Compiler zu Compiler und Architektur zu architektur unterschiedlich sein kann, wie die Objekte im Speicher gehandhabt werden ...

    Das sicherste ist Zeiger der Basisklasse verwenden und mit Virtuellen Funktionen zu arbeiten. Im OOP Idealfall sollten ja keinerlei Variablen eines Objektes von aussen erreichbar sein ... das halte ich aber fuer uebertrieben und kaum realisierbar .. zumindest hab ichs noch nie komplett hinbekommen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •