Typlose Zeiger in C++



  • Ich merke schon, das Tema wird nicht leicht, da wird man schon beleidigt.
    Hast ja recht "Shade Of Mine"; programmiere erst seit 3 Jahren in C++ und 19 Jahre in Assembler. Doch was mir bei C++ aufällt ist, daß sobald man an IO Operationen ran muss und damit auf Systemkomponenten zugreift, wird C++ sehr umständlich und langsam - dafür hat man natürlich eine ausgesprochene Kompatibilität. Und damit gleichmal zur Schnellchkeit, wo ich dich berichtigen muss und ich wohl jede Menge Rückendeckung habe: Assembler ist natürlich viel schneller und mit keiner Hochsprache zu vergleichen; dafür bleibt natürlich die Portabilität auf der Strecke.Das ist auch der Hauptgrung warum ich hier bin und dieses Problem gerne mit C++ bewältigen will. Dabei muss ich aber die Typüberprüfung ("vom gleichen Typ") umgehen und muß definieren:
    "von der gleichen Länge mit der selben Startadresse" im prinzip C++ etwas Verantwortung abnehmen.

    Alle Typen die ich so behandle sind Datensätze (z.B. 78byte lang manche auch unbestimmt und werden im zweiten Teil mit new erweitert) aus Dateien.
    Der Datensatz ist definiert als typedev struct, also eine Klasse.
    Der Datensatztyp enthält auch andere Typedev struct, hat also andere Klassenelemente.
    Dürfte bis dahin kein Problem sein, solange, sobald die Länge sizeof() verfügbar ist und einen zusammenhängenden bereich im Speicher einnehmen. Also die Datensätze mit new kann ich im ganzen vergessen, da muss ich zwei Teile draus machen; einen der eingelesen werden kann (der enthält auch die Anzahl für die mit new zu erstellenden Datensätze, die mit new erzeugten Datensätze haben dann wiederum einen zusammenhängend Bereich (new type[n]))

    static_cast, da muss ich mich mal schlau machen ... dürfte aber kein Problem sein, da die Typen alle global definiert sind....

    type-casting ...
    dynamic_cast <new_type> (expression)
    reinterpret_cast <new_type> (expression)
    static_cast <new_type> (expression)
    const_cast <new_type> (expression)

    Ich denke mal das funktioniert mit dynamic_cast dann auch für meine Typen mit klassenelementen und Funktionen

    Also, ich will alle Member meiner Datenbankklasse mit der Typlänge und der dazugehörigen Basisadresse füttern. Bleiben wir bei diesem Problem dann habe ich genügend Übung für das andere.

    Lese mir dann erst noch Artikel zur Awendung dieser Funktionen durch - also ich bin dann mal am studieren. (dann kann ich auch mitreden)

    Bin mal kurz schlafen, bis gleich

    bastl



  • bastl schrieb:

    Ich merke schon, das Tema wird nicht leicht, da wird man schon beleidigt.

    Davon sehe ich hier nichts, falls du das mit den Wissensgrenzen meinst, so scheint dies zumindestens bezüglich C++ tatsächlich zu stimmen - dies ist aber keine Beleidigung, sondern das was man aus deinen Beschreibungen ablesen kann. Dies kann unter anderem an deiner langen Assemblerlaufbahn liegen, da man C++ eigentlich auf eine gänzlich andere Art benutzt als Assembler (Andere Ansätze, andere Paradigmen).

    bastl schrieb:

    Doch was mir bei C++ aufällt ist, daß sobald man an IO Operationen ran muss und damit auf Systemkomponenten zugreift, wird C++ sehr umständlich und langsam - dafür hat man natürlich eine ausgesprochene Kompatibilität.

    Ich habe persönlich nur wenig Assemblererfahrungen, aber wenn die IO-Umsetzung der Standardbibliothek nicht gepuffert ist etc. kann diese auch langsam sein (z.B. sind die Streams unter Microsoft Visual C++ tendenziell langsam, wenn man ihnen keinen Buffer zuweist).

    Zudem ist alles was ich inzwischen gehört habe, das C++ sich nicht wirklich hinter Assembler verstecken muss, und spätestens bei großen Anwendungen ist mit Sicherheit die Entwicklungszeit noch ein sehr wichtiges Argument. Je nach dem wie man C++ einsetzt kann es sehr langsam sein, aber ebenso kann man sehr schnelle Programme schreiben.

    bastl schrieb:

    ...Der Datensatz ist definiert als typedev struct, also eine Klasse... new type[n]... alle global definiert...

    Dies sind Dinge die schon darauf hinweisen, das du eher C als C++ entwickelst (unter C++ ist die schreibweise "typedef struct" mehr als unüblich, dies ist eher ein typisches C-Relikt; C-Arrays sind - wie der Name schon sagt auch eher in C als in C++ zu finden). Auch deine Typbeschreibung deutet eher von einer Assemblersichtweise hin. Dies mag auch dazu führen das du dein Problem in einer weise schilderst die für mich aus der C++ Sicht eher schwer verständlich ist.

    Vielleicht löst du dich etwas von deiner stark technischen Beschreibung, und erklärst deine Problematik mal ohne Nennung von irgendwelchen Implementationsdetails (Außer vielleicht bezogen auf die Eingangsgrößen und Ausgangsgrößen).

    dynamic_cast ist übrigens für polymorphe Objekte (Umwandlung von einen Zeiger einer Basisklasse in einen Zeiger einer abgeleiteten, polymorphen [Thema virtuelle Funktionen] Klasse), nicht für normale Typumwandlungen.

    Zudem, mag sein das ich das auch aus deinem Text falsch ablese, solltest du dir bezüglich new/new[] nochmal Gedanken machen. Mit new erzeugte Einzelobjekte und ein mit new Erzeuges Array sind unterschiedliche Dinge...

    cu André



  • bastl schrieb:

    Doch was mir bei C++ aufällt ist, daß sobald man an IO Operationen ran muss und damit auf Systemkomponenten zugreift, wird C++ sehr umständlich und langsam - dafür hat man natürlich eine ausgesprochene Kompatibilität.

    Wenn du mit IO die IOStreams meinst - die sind für komfort optimiert, du kannst jederzeit aber ein CreateFile/WriteFile machen wie du es in Assembler auch machen würdest...

    Und damit gleichmal zur Schnellchkeit, wo ich dich berichtigen muss und ich wohl jede Menge Rückendeckung habe: Assembler ist natürlich viel schneller und mit keiner Hochsprache zu vergleichen;

    Ich wage es zu bezweifeln dass man komplexe programme in assembler effizienter programmieren kann als in einer hochsprache wie C++. Kleine Stellen in Algorithmen ja, aber generell nein.

    Ich denke mal das funktioniert mit dynamic_cast dann auch für meine Typen mit klassenelementen und Funktionen

    Äh... Nein.
    Erkläre bitte was du machen willst - nicht welche C++ Mittel du einsetzen willst.

    Willst du rohen Speicher als Objekte unterschiedlicher Typen betrachten?
    Warum?

    Oder willst du einfach ein abstraktes Typsystem haben, im Sinne von: die Funktion foo() liefert einen Wert den man als integer, double, string oder sonstwas interpretieren kann? Ähnlich wie einer ScriptSprache mit DuckTyping?

    Oder willst du soetwas wie bei einer Datenbank API üblich: du machst "select foo from bar" und je nachdem welchen Typ foo hat soll dementsprechend ein passendes objekt zurück gegeben werden? uU kann man foo als integer und als string betrachten und das willst du im client dann durchweselbar machen?

    uU suchst du auch einfach nur "union" oder variant/any.

    deshalb: erkläre _was_ du machen willst und _warum_ und nicht _wie_. Denn das _wie_ sagen wir dir dann...

    PS:
    und beleidigen will ich dich sicher nicht, aber dein C++ Wissen scheint mir nunmal nicht wirklich umfassend zu sein. Ist ja keine Beleidigung, einfach nur eine feststellung.



  • So wie ich das verstanden habe, hat er Typen, welche u.a. Zeiger auf andere Typen enthalten. Den Zeigern kann dann bei Bedarf allokierter Speicher (auf die anderen Typen) zugeordnet werden. Nun meint er, dass dabei die Speichebereiche nicht zusammenhängend sein können.
    Das können sie aber. Das geht mit placement new .



  • Tachyon schrieb:

    So wie ich das verstanden habe, hat er Typen, welche u.a. Zeiger auf andere Typen enthalten. Den Zeigern kann dann bei Bedarf allokierter Speicher (auf die anderen Typen) zugeordnet werden. Nun meint er, dass dabei die Speichebereiche nicht zusammenhängend sein können.
    Das können sie aber. Das geht mit placement new .

    O_o

    das habe ich nichtmal annäherend herausgelesen. ich denke eher dass er richtung ducktyping will... aber ok - da muss er wohl näher erklären was er will...



  • Shade Of Mine schrieb:

    das habe ich nichtmal annäherend herausgelesen. ich denke eher dass er richtung ducktyping will... aber ok - da muss er wohl näher erklären was er will...

    Okay, wenn's das wirklich sein sollte, dann wäre Assembler so ziemlich das Letzte, womit ich das implementieren wollte. Ich wäre da nichtmal auf die Idee gekommen, das im gleichen Atemzug zu erwähnen. 😮

    Wenn ich mir den Eröffnungspost nochmal durchlese, hast Du vermutlich sogar recht. Ich habe mir meine Vermutung irgendwie aus der Antwort auf Deinen Vorschlag zusammengereimt.



  • Tachyon schrieb:

    Wenn ich mir den Eröffnungspost nochmal durchlese, hast Du vermutlich sogar recht. Ich habe mir meine Vermutung irgendwie aus der Antwort auf Deinen Vorschlag zusammengereimt.

    Ja das mit dem new hab ich nichtmal ansatzweise kapiert was er will 😕



  • Der gewünschte Benutzerna schrieb:

    Kann man nun void *zeiger dazu benützen nacheinander mit dem gleichen Zeiger unterschiedliche formatierungen anzusprechen, die die gleiche Länge haben?

    Ohje, das ist totaler Nonsense. Man kann das technisch zwar machen, aber das ganze ist nicht mehr portabel, da hier solche Dinge wie Padding, Aligment, Byte Order etc. zum Tragen kommen. Wenn man Assembler programmiert, kann man das so machen, da der Code ohnehin nicht portabel ist, sobald man aber mit C++ anfängt muß man davon die Finger lassen.



  • Mich würde mal interessieren, was überhaupt mit dem Wort "Formatierung" in diesem Zusammenhang gemeint ist.



  • ~john schrieb:

    Ohje, das ist totaler Nonsense. Man kann das technisch zwar machen, aber das ganze ist nicht mehr portabel, da hier solche Dinge wie Padding, Aligment, Byte Order etc. zum Tragen kommen. Wenn man Assembler programmiert, kann man das so machen, da der Code ohnehin nicht portabel ist, sobald man aber mit C++ anfängt muß man davon die Finger lassen.

    Das ist ebenfalls Nonsense. Nicht jedes C++ Programm ist dafür gedacht, portabel zu sein. Manchmal will man auch einfach nur schnell zu einer effizienten, günstigen Lösung kommen. Portabel sind C++-Programme schon dann nicht mehr, wenn sie plattformspezifische Bibliotheken benutzen, und das machen eine Menge Programme...



  • asc schrieb:

    Dies sind Dinge die schon darauf hinweisen, das du eher C als C++ entwickelst (unter C++ ist die schreibweise "typedef struct" mehr als unüblich, dies ist eher ein typisches C-Relikt; C-Arrays sind - wie der Name schon sagt auch eher in C als in C++ zu finden). Auch deine Typbeschreibung deutet eher von einer Assemblersichtweise hin.

    Also asc Ich hätte dann auch schon gerne, daß du die C Thematik dann auch für C++ angibst (wie man es in C++ richtig macht).
    Ich benötige einen Typnamen (z.B. für new), jedoch keinen Klassennamen außer für meine dynamische Typen. Wenn gcc es halt nicht anders akzeptiert musst du mir einen Vorschlag machen - ich probiere das gerne aus.

    -----
    Zu dir Shade Of Mine, das unterschiedliche formatieren eines Speicherbereiches lassen wir mal beiseite, wird sonst zu kompliziert hier auf zwei Probleme einzugehen. Das eigentliche Problem ist also die Datenbankklasse mit den normalen Members, die man so braucht, read, write, und und das einstreamen unterschiedlicher Typen (Längen von 10 Byte bis 10 MB pro Typ).
    Ich kann jetzt für jede Datenbank eine eigene Klasse schreiben (ca. 50 Stück) oder eine Klasse für alle Datenbanken. Daraus ergibt sich die Problematik der unterschiedlichen Typen. Das hat dazu gefhürt die Möglichkeit hier zu erörtern, ob dies ohne gröpßeren Aufwand möglich ist. Eine und für mich die plausibelste Mölichkeit ist, den Basiszeiger eines zusammenhängenden Speicherbereiches zu übergeben und die dazugehöige Länge, ist ja oben schon beschrieben. Manche Typen müssen mehrfach in Stücken eingelesen werden, da diese Datenbanken aus dynamischen Datensätzen bestehen.Wir können hier nur abstrakt erörtern, das muss ich auch beim programieren so machen.

    Und ich muss hier auch sagen, daß man C++ nicht programieren kann ohne zu wissen wie der Kompiler funktioniert. Man muss genau wissen wie werden Daten im Speicher abgelegt, was macht new und wie verhält sich was wenn man es so programmiert; da kommt mir meine Assembler Erfahrung teilweise schon zugute.

    Und was Assembler angeht muss ich hier auch noch was loßwerden, Ich programiere mit Assembler jetzt schon seit ca 15 Jahren Opjekt Orientiert und solche Sachen wie X11 oder QT sind nichts besonderes in Assembler und durchaus einfacher zu programieren als mit C++. Sowas wie X11 und QT in Einem habe ich schon in Assembler programmiert - das waren noch Zeiten unter DOS ...
    ------

    Tachyon schrieb:

    So wie ich das verstanden habe, hat er Typen, welche u.a. Zeiger auf andere Typen enthalten. Den Zeigern kann dann bei Bedarf allokierter Speicher (auf die anderen Typen) zugeordnet werden.

    Keine Zeiger, aber der Datensatz ermöglicht es mit seiner enthaltenen Info ihn zu vervollständigen (man kann mit dem ersten Teil den noch fehlenden Teil ausrechnen). Jetzt ist es so, daß mich zwei nicht zusammenhängende Blöcke aber nicht stören, da diese Typen sowieso dynamisch sind und auf zweimal eingelesen werden müssen. Was placement angeht - ja, deshalp wird ein ARRAY von Typen mit new erzeugt - dann ist es automatisch zusammenhägnend.(mit new erzeugte arrays und strings sind immer zusammenhängend)

    2.) Mit Assembler kann ich halt den kompletten dynamischen Datensatz auf einmal einlesen und c++ die nötige Info dazu liefern (Laufzeitimplementierung).

    ducktyping betrift die Umformatierung was ich vorerst hier mal weglassen will.
    ------

    Shade Of Mine schrieb:

    Ja das mit dem new hab ich nichtmal ansatzweise kapiert was er will 😕

    Was braucht ihr da für Info? - Wenn es in diesem Block nicht stehen sollte.

    Wie sieht es nun mit void *zeiger aus? Ist der Geltungsbereich dann nur innerhalb der Funktion, in der ich diesen void *zeiger benutze? Oder überträgt sich das auf die nächsten Aufrufe? Jeder Aufruf der Funktion ist ja mit einem Zeiger auf einen Typ, der eine Länge hat, die sich von der des vorherigen Aufrufs unterscheidet. Ich vermute mal, daß der Geltungspereich die Funktion ist und somit void *auf_gleiche_laenge nur innerhalb der Funktion gilt.



  • Decimad schrieb:

    Mich würde mal interessieren, was überhaupt mit dem Wort "Formatierung" in diesem Zusammenhang gemeint ist.

    Ich denke schon, daß dies ein kompakter Ausdruck ist, der angemessen ist.
    - Wenn 2 Typen gleicher Länge (z.B Typ1 mit 8 chars und Typ2 mit 2 ints) die gleiche Basisadresse haben. Der Seicherbereich ab Basisadresse hat somit 2 unterschiedliche ansprechbare Formate oder anders ausgedrückt: ein Typ formatiert lediglich einen Abschnit im Speicher ab Basisadresse. Speicher ist Speicher und besteht aus Bits erst eine Formatierung sagt mir wie ich einen Speicherbereich benützen soll, muss, darf - so will es C++.



  • ~john schrieb:

    Ohje, das ist totaler Nonsense. Man kann das technisch zwar machen, aber das ganze ist nicht mehr portabel, da hier solche Dinge wie Padding, Aligment, Byte Order etc. zum Tragen kommen. Wenn man Assembler programmiert, kann man das so machen, da der Code ohnehin nicht portabel ist, sobald man aber mit C++ anfängt muß man davon die Finger lassen.

    Da hast du absolut Recht, jetzt muss ich abwegen ....

    IA64 - O.K. davon gehe ich aus.
    Apple hat jetzt IA86 - O.K.
    Sparc - Nein, das ist nicht gut
    S390 - Nein, garnicht gut

    In 2 Jahren hab ich vielleicht die erste Version dann gibt es vieleicht schon einen IA64 64 core dann läuft das Programm auch ordentlich.
    O.K. ich verzichte auf Portabilität.



  • bastl schrieb:

    asc schrieb:

    Dies sind Dinge die schon darauf hinweisen, das du eher C als C++ entwickelst (unter C++ ist die schreibweise "typedef struct" mehr als unüblich, dies ist eher ein typisches C-Relikt; C-Arrays sind - wie der Name schon sagt auch eher in C als in C++ zu finden). Auch deine Typbeschreibung deutet eher von einer Assemblersichtweise hin.

    Also asc Ich hätte dann auch schon gerne, daß du die C Thematik dann auch für C++ angibst (wie man es in C++ richtig macht).

    1. typedef struct ist redundant. Jede struct, class, enum, union ist bereits eine Typdefinition. Das typedef lässt man daher weg. Nachfolgender Code definiert einen Typ xtyp:

    struct xtyp { int x; };
    

    bastl schrieb:

    Ich benötige einen Typnamen (z.B. für new), jedoch keinen Klassennamen außer für meine dynamische Typen

    Keine Ahnung was du damit meinst (Ein Klassenname IST ein Typenname).

    2. Unter C++ verwendet man C-Array eher selten, da es weder sinnvoll Kopiert etc. Statt dessen sind eigentlich die Containerklassen der Standardbibliothek in Verwendung (std::vector, std::list, std::map, std::tr1::array...).

    3. void* ist nicht für delete geeignet. delete benötigt Typinformationen, die erhält es durch ein void* nicht. Wenn du unbedingt mit rohen Speicher hantieren willst, würde ich eher ein char* oder std::vector<char> nehmen, dann kannst du es wenigstens byteweise interpretieren.

    Ebenso kann man void* nur benutzen wenn man weiß wie man die Daten zu interpretieren hat.

    C++ arbeitet nun einmal mit einem statischen Typsystem.

    bastl schrieb:

    Und ich muss hier auch sagen, daß man C++ nicht programieren kann ohne zu wissen wie der Kompiler funktioniert. Man muss genau wissen wie werden Daten im Speicher abgelegt, was macht new und wie verhält sich was wenn man es so programmiert

    Das ist absoluter Nonsense, es sei vielleicht, man will alles auf binärer Ebene bearbeiten, was eigentlich in C++ nicht üblich ist - Dann sollte man gleich in Assembler weiterarbeiten.

    Eine Programmiersprache ist ein Werkzeug um eine Aufgabe zu erledigen. Das man ungefähre Vorstellung hat, wie etwas realisiert werden könnte kann manchmal hilfreich, nicht selten aber auch die sprichwörtlichen Scheuklappen sein. Um ein Ziel zu erreichen sollte es - zumindestens in einer Hochsprache - vollkommen egal sein was der Compiler im Hintergrund daraus macht.

    bastl schrieb:

    Was placement angeht - ja, deshalp wird ein ARRAY von Typen mit new erzeugt - dann ist es automatisch zusammenhägnend.(mit new erzeugte arrays und strings sind immer zusammenhängend)

    Das ist auch beim std::vector oder std::tr1::array definiert.

    cu André



  • Tachyon schrieb:

    Das ist ebenfalls Nonsense. Nicht jedes C++ Programm ist dafür gedacht, portabel zu sein. Manchmal will man auch einfach nur schnell zu einer effizienten, günstigen Lösung kommen. Portabel sind C++-Programme schon dann nicht mehr, wenn sie plattformspezifische Bibliotheken benutzen, und das machen eine Menge Programme...

    Das ist totaler Quatsch! (Wohl bisher nur unter Windows gearbeitet?) UNIX Programme verwenden seit Jahrzehnten spezielle UNIX Libraries und laufen trotzdem auf sehr vielen verschiedenen Prozessorachitekturen.

    Wenn man unter UNIX, Linux oder Windows entwickelt, dann gibt es mehr als eine Prozessorarchitektur! Bei Windows gibt es IA32, IA32-64, IA64 bei den anderen Plattformen kommen noch Power, HP-PA, SPARC, ARM, MIPS etc. dazu. Wenn man da ohne Not von einer spezifischen Anordnung der Daten ausgeht, baut man einfach nur Mist. Zum Beispiel sollen Daten ja auch unabhängig vom 32Bit oder 64Bit Modus eingelesen werden können, und es gibt Betriebssysteme die laufen nicht nur auf einer Hardwarearchitektur. Wenn man nicht gerade an Computerspielen oder ähnlich zeitkritischen Programmen arbeitet sollte man die Finger von Mikrooptimierungen lassen, denn in der Regel lebt der Code länger als einem beim Entwerfen bewußt ist.



  • bastl schrieb:

    IA64 - O.K. davon gehe ich aus.
    Apple hat jetzt IA86 - O.K.
    Sparc - Nein, das ist nicht gut
    S390 - Nein, garnicht gut

    In 2 Jahren hab ich vielleicht die erste Version dann gibt es vieleicht schon einen IA64 64 core dann läuft das Programm auch ordentlich.
    O.K. ich verzichte auf Portabilität.

    1. Du meinst IA32-64. IA64 wäre der Itanium! Windows läuft auf IA64.
    2. Es ist auch über verschiedene Compilerversionen nicht portabel!



  • ~john schrieb:

    Das ist totaler Quatsch! (Wohl bisher nur unter Windows gearbeitet?) UNIX Programme verwenden seit Jahrzehnten spezielle UNIX Libraries und laufen trotzdem auf sehr vielen verschiedenen Prozessorachitekturen.

    Es gibt Ausnahmen, die Regel (zumindestens in der Anwendungsentwicklung in kommerziell orientierten Projekten), ist es möglichst schnell eine Lösung zu präsentieren. Und dazu greifen viele Firmen auf OS-Spezifische Bibliotheken zu.

    Man kann C++ auch sehr portabel schreiben (das es unter vielen Betriebssystemen wieder gelinkt werden kann), aber das erlebe ich eigentlich eher selten. Auch wenn ich selbst ein Fan davon bin in Anwendungen zumindestens die Schichten zwischen UI auf der einen, und Datenzugriff auf der anderen Seite weitgehend portabel zu halten.

    cu André



  • bastl schrieb:

    Ich benötige einen Typnamen (z.B. für new), jedoch keinen Klassennamen außer für meine dynamische Typen.

    "struct" und "class" sind in C++ fast dasselbe. Es sind auch Typen, aber es gibt weitere Arten von Typen.

    bastl schrieb:

    Zu dir Shade Of Mine, das unterschiedliche formatieren eines Speicherbereiches lassen wir mal beiseite, wird sonst zu kompliziert hier auf zwei Probleme einzugehen. Das eigentliche Problem ist also die Datenbankklasse mit den normalen Members, die man so braucht, read, write, und und das einstreamen unterschiedlicher Typen (Längen von 10 Byte bis 10 MB pro Typ).

    Was willst Du machen? Objektgraphen (de)serialisieren oder RDBMS Abfragen auf ein RDBMS loslassen? Davon hängt maßgeblich ab, wie man es umsetzt.



  • bastl schrieb:

    Ich benötige einen Typnamen (z.B. für new), jedoch keinen Klassennamen außer für meine dynamische Typen. Wenn gcc es halt nicht anders akzeptiert musst du mir einen Vorschlag machen - ich probiere das gerne aus.

    Ich glaube ich habe verstanden was du machen willst.
    Aber eine schoene Erklaerung waere nicht schlecht - da muss man nicht soviel raten.

    Du kannst rohen Speicher besorgen:

    void* p = ::operator new(100);
    

    das besorgt die 100 byte Speicher.

    Nun kannst du wenn du zB eine struct Foo oder Bar hast:

    struct Foo { int i[5]; }
    struct Bar { double d[5]; }
    

    Theoretisch ein:

    Foo* f = static_cast<Foo*>(p);
    Bar* b = static_cast<Bar*>(p);
    

    machen - oder aber mit einer Union arbeiten.

    Aber das ist mit sehr grosser Wahrscheinlichkeit genau das falsche vorgehen...

    Das eigentliche Problem ist also die Datenbankklasse mit den normalen Members, die man so braucht, read, write, und und das einstreamen unterschiedlicher Typen (Längen von 10 Byte bis 10 MB pro Typ).
    Ich kann jetzt für jede Datenbank eine eigene Klasse schreiben (ca. 50 Stück) oder eine Klasse für alle Datenbanken.

    Meinst du wirklich 50 unterschiedliche Datenbanken? Oder meinst du 50 unterschiedliche typen?

    Jedenfalls:
    Wenn du Datenbanken meinst - da verwendet man ein vereinheitlichtes interface (zB ODBC, ADO,...) um auf sie zuzugreifen und muss nur gegebenenfalls leicht adaptieren.
    Wenn du Typen meinst: ja, dann musst du 50+ Klassen schreiben, wobei die meisten klassen sehr sehr sehr klein sein werden.

    Daraus ergibt sich die Problematik der unterschiedlichen Typen. Das hat dazu gefhürt die Möglichkeit hier zu erörtern, ob dies ohne gröpßeren Aufwand möglich ist. Eine und für mich die plausibelste Mölichkeit ist, den Basiszeiger eines zusammenhängenden Speicherbereiches zu übergeben und die dazugehöige Länge, ist ja oben schon beschrieben. Manche Typen müssen mehrfach in Stücken eingelesen werden, da diese Datenbanken aus dynamischen Datensätzen bestehen.Wir können hier nur abstrakt erörtern, das muss ich auch beim programieren so machen.

    Nein - nicht sagen wie du es machen willst. Einfach erklaeren _was_ du machen willst. Und zwar mit der richtigen terminologie.

    Und was Assembler angeht muss ich hier auch noch was loßwerden, Ich programiere mit Assembler jetzt schon seit ca 15 Jahren Opjekt Orientiert und solche Sachen wie X11 oder QT sind nichts besonderes in Assembler und durchaus einfacher zu programieren als mit C++. Sowas wie X11 und QT in Einem habe ich schon in Assembler programmiert - das waren noch Zeiten unter DOS ...

    Und dennoch bist du unfaehig ein Problem zu _beschreiben_?

    2.) Mit Assembler kann ich halt den kompletten dynamischen Datensatz auf einmal einlesen und c++ die nötige Info dazu liefern (Laufzeitimplementierung).

    Du kannst in C++ sehr wohl nur rohe daten anfassen...

    Was braucht ihr da für Info? - Wenn es in diesem Block nicht stehen sollte.

    Eine korrekte terminologie brauche ich und keine erklaerung was du mit basisklassenzeiger machen willst oder sonstwas. ein _was_ du machen willst brauche ich, kein _wie_.

    Erklaer die Aufgabenstellung einfach mal so, wie du sie einem Schueler stellen wuerdest. zB:

    Wir haben ein Datenbank System entwickelt. Nun brauchen wir eine Moeglichkeit Daten unterschiedlicher Typen hinein zuschreiben und wieder auszulesen. Das Problem dabei ist nun, dass der Client Code nicht weiss welchen Typ ein Datensatz hat. Wir brauchen daher ein vereinheitlichtes system um auf 50 verschiedene typen ueber das selbe interface zugreifen zu koennen.

    So in der Art bitte.

    Wie sieht es nun mit void *zeiger aus? Ist der Geltungsbereich dann nur innerhalb der Funktion, in der ich diesen void *zeiger benutze?

    Aeh... Das sind eigentlich Grundlagen - programmierst du wirklich schon 3 jahre lang in C++?
    Naja, jedenfalls: eine variable (ein zeiger ist auch nur eine variable) ist in ihrer gueltigkeit durch ihren Scope beschraenkt. Der Speicher auf den ein Zeiger zeigt unterliegt ebenfalls einem Scope: speicher am Stack wird geloescht wenn die stack-variable out of scope geht. Speicher der am Free Store liegt, bleibt solange bestehen bis er explizit geloescht wird (delete).

    Oder überträgt sich das auf die nächsten Aufrufe? Jeder Aufruf der Funktion ist ja mit einem Zeiger auf einen Typ, der eine Länge hat, die sich von der des vorherigen Aufrufs unterscheidet. Ich vermute mal, daß der Geltungspereich die Funktion ist und somit void *auf_gleiche_laenge nur innerhalb der Funktion gilt.

    Das ergibt fuer mich keinen Sinn.
    sizeof(void*) und sizeof(T*) sind uebrigens gleich gross...



  • ~john schrieb:

    ...sabber...

    Es gibt noch andere Dinge als Unix und Windows. DSPs z.B., oder Mikrocontroller. Oder die gute alten VAX und deren Nachfolger. Irgendwie habe ich da so meine Probleme die der Portabilität, wenn ich Unix-Libraries benutze. Keine Ahnung, woher das kommt. 🙄

    Und Mist baut man nicht, wenn man von einer spezifischen Anordnung der Daten ausgeht (dann ist man sich nämlich der Probelematik bewusst), sondern wenn man sie außer Acht lässt.


Anmelden zum Antworten