object in c++



  • Hallo. Jo void* ist ne Idee.

    Allerdings stoße ich nun auf das Umwandlungsproblem.
    Übergebe also einer Funktion einen void*

    in dieser Funktion wird anhand eines Wertes und mit Hilfe einer Switch Case Anweisung entschieden um welchen Datentyp es sich handelt.

    switch(datatype)
    {
    case BIT:
    Write((bool)(*void));
    break;

    case INT
    WRITE((int)(*void));
    break;

    usw.
    }

    Hier erhalte ich nun den Compilerfehler:
    - Ungültige Dereferenzierung.

    Wie caste ich hier richtig?



  • Du castest erst auf den Zeigertyp, dann derefernzierst du.



  • Sprich so:

    Write(*((int*)value));
    

    Ok das funktioniert. Klar andersrum gehts ja nicht. Nen void Pointer zu dereferenzieren geht schlecht.



  • Jetzt habe ich aber noch ein anderes Problem.
    Der Datentyp aus meiner Switch case Anweisung muss nicht der gleiche Datentyp sein den ich mit void* übergebe.

    Beispiel:

    Ich übergebe einen CString mit einem Wert von 10. Mein Datentyp ist ein short.
    Nun muss ich ja zuerst auf CString casten und danach auf short.

    Wie bekomme ich raus welcher Datentyp wirklich in void* steckt?



  • Das geht in native Code nicht.. Du kannst höchstens einen Container-Typ wie VARIANT verwenden, der auch die Typ-Infos enthält...



  • Genau, in Code eine recht einfache Variante:

    strukt Value
    {
      int type; // (oder enum ..)
      void* value;
    };
    


  • Mist. VARIANT geht auch nicht.

    Also vieleicht mal mein Problem weiter ausgeführt.
    Ich lese von einem Dialog einen Wert ein. Dieser ist ein CString. Dieser Wert soll nun an meine erwähnte Funktion übergeben werden. Diese entscheidet nun anhand einer weiteren auswahl in welchen Datentyp dieser Wert konvertiert werden soll. Soweit wäre das ja kein Problem. Dann könnte ich der Funktion ja immer einen CString übergeben. Die Funktion wird aber nicht nur mit dem Wert aus dem Dialog aufgerufen sondern auch mit anderen Werten. Also z.B. short, int, double, usw. Also benötige ich einen unabhängigen Datentyp.

    Ich muss eine Funktionalität nach programmieren die in c# programmiert wurde. Und dort wurde halt der Datentyp object verwendet.

    Hat mir jemand noch nen Lösungsansatz?



  • (schrei): VARIANT!



  • (schrei): VARIANT!

    Ja ok. Wollte halt nicht vorher noch sagen müssen was das für ein Typ ist den ich übergebe. Aber es geht ja nicht anders.



  • Und wie mache ich dann weiter. Jetzt entscheide ich anhand den Variantyps in was ich als erstes casten muss. Nun kann ich ja verschiedenste Variablen erhalten. Diese muss ich ja nun wieder anhand des "Datentyps" weiter casten. Wie mache ich das ohne ein riesen konstrukt an verschachteleter switch case anweisungen?



  • Hab ich jetzt nicht ganz verstanden... Was musst Du denn da "weiter casten"? Ich dachte Du stopfst nur einb Datentyp rein?

    Du kannst das ganze ja aber auch rekurzsiv machen... in einen VARAINT einen anderen VARIANT reinstopfen...



  • Hab ich jetzt nicht ganz verstanden... Was musst Du denn da "weiter casten"? Ich dachte Du stopfst nur einb Datentyp rein?

    Also ich stopf nun einen VARIANT rein. Der ist dann in unserem Beispiel ein CString bzw. BSTR im VARIANT.

    so nun holle ich den Wert aus dem VARIANT. Dass muss ich ja dann z.B. mit einem switch case machen. Nun muss ich den Wert wie anfänglich beschrieben in einen Datentyp casten der ausgewählt wurde. z.B. Int.

    switch (value.vt)
    {
      case VT_BSTR:
        switch(datatype)
        {
          case BIT:
              Write((bool)value.bstrVal);
              break;
          case INT:
              Write((int)value.bstrVal);
              break;
          ...
    
        }
    
      case VT_I4:
        switch(datatype)
        {
          case BIT:
             Write((bool)value.intVal);
             break;
    
          ...
        }
    }
    


  • Die Funktion wird aber nicht nur mit dem Wert aus dem Dialog aufgerufen sondern auch mit anderen Werten. Also z.B. short, int, double, usw. Also benötige ich einen unabhängigen Datentyp.

    Das wuerde fuer mich eher ein Fall fuer Ueberladung sein.

    Ach ja: du kannst nicht durch casten einen String in einen Integer verwandeln. Casten ist was fuer Typen, nicht fuer Werte.



  • Das wuerde fuer mich eher ein Fall fuer Ueberladung sein.
    

    Im Prinzip hast du recht. Da mein C++ Projekt dem bereits erwähnten c# Projekt aber (fast) gleich sein sollte wollte ich auch hier nur eine Funktion. Klar wenn es nicht anders geht muss ich dann halt doch überladen 😞



  • Aber wenn ich Überladungen nehme habe ich auch das Problem dass ich sehr viele switch case Konstrukte habe. Nur halt dieses mal in vielen Funktionen verteilt. Was ich auch nicht schön finde.



  • Ich verstehe es nicht ganz....

    Du hast doch blos ein "value" und da steckt der Wert *und* der Typ drin... was soll denn in Deinem Beispiel das "datatype" sein? Wo kommt das her?



  • Du hast doch blos ein "value" und da steckt der Wert *und* der Typ drin... was soll denn in Deinem Beispiel das "datatype" sein? Wo kommt das her?

    Nein ich habe 2 Datentypen.
    "Datatype" kommt von der Oberfläche. Also noch weiter ausgeholt. Ich lese eine Liste von Variablen von einem anderen System ein und stelle diese Werte in einer Liste dar. Nun kann ich einen Variable aus der Liste auswählen und erhalte von ihr, den aktuellen Wert und ihren Datentyp.

    z.b.

    Name: Info
    Typ: Double
    Wert: 5.0

    So nun möchte ich den Wert ändern. Schreibe in die Textbox den neuen wert von 10. So da dies nun immer ein anderer Datentyp sein kann, ist das Textfeld ein String wert.

    Also nun steht eine 10 im Textfeld. Diese 10 soll nun der besagten Funktion übergeben werden. Und da die Funktion aber auch von einer anderen Stelle aufgerufen werden kann, muss diese Funktion nicht nur String entgegen nehmen sondern auch andere Werte. Deshal in c# object und in c++ void* oder VARIANT.

    Nun muss ich also in der Funktion den Wert aus dem Parameter heraus bekommen.

    Also z.B. der besagte String. Meine erstes switch case. Nun muss ich ja aber den wert, in unserem Beispiel, noch in double wandeln.

    Nun klar?



  • Ich verstehe nicht, warum Du Deinen "datatype" nicht in "value.vt" packst...

    Oder wenn Du willst auch einen eigene Struktur dafür machst:

    tyepdef struct tMyVariant {
      DataTypes datatyp;
      union {
        int integer;
        bool boolean;
        std::string string; 
        // usw.
      }
    };
    


  • Ich pack doch meinen Datentyp in value.vt
    Und da steht nun "String" drin.

    Und nun weiß ich dass in meinem VARIANT ein String drin ist. Aber den String muss ich doch nun noch in einen double wandeln.



  • Ja ok.. dann hast Du halt zwei Ebenen... hab es zwar immer noch nicht ganz verstanden, warum Du das brauchst... aber egal...

    Du hattest doch geschrieben dass Du als "Input" *immer* einen String bekommst... also gibt es doch nur eine Ebene, da die zweite ja immer "String" ist, oder?


Anmelden zum Antworten