Verständnisproblem mit operator DWORD () und CString::Format ()



  • Hallo zusammen,

    Worum geht es:
    Der RemoteControler empfängt benannte Daten zB. <Data Name="ClassNum" Value="255" /> diese Daten werden im RemoteControler in einer map<string, DWORD> gespeichert.

    In der Applikation möchte ich nun eine DWORD variable haben welche immer den aktuellen Zustand von zB. map[ClassNum] hat.

    Header: RemoteControl.h

    class RxDataVal
    {
    public:
      RxDataVal      ();
      operator DWORD ();
    
    private:
      RxDataVal&  operator= (DWORD* val);
      DWORD*      mValue;
    
    friend class RemoteControl;
    };
    

    friend dient hier der Sicherheit! So kann ausschliesslich der RemoteControler den Wert der Variablen ändern.

    Source: RemoteControl.cpp

    RxDataVal::RxDataVal ()
    : mValue	(NULL)
    {}
    
    RxDataVal::operator DWORD ()
    {
      return *mValue;
    }
    
    RxDataVal& RxDataVal::operator = (DWORD* val)
    {
      mValue = val;
      return *this;
    }
    
    RxDataVal TRemoteControl::GetReceiveDataVar (const Tstring name)
    {
      RxDataVal var;
      if (mMaster)
      {
        for (size_t i = 0; i < mConfig->mSlaveData.size (); ++i)
        {
          if (name == mConfig->mSlaveData[i])
            var.mValue = &mSlaveData[name];
        }
      }
      else
      {
        for (size_t i = 0; i < mConfig->mMasterData.size (); ++i)
        {
          if (name == mConfig->mMasterData[i])
            var.mValue = &mMasterData[name];
        }
      }
      ASSERT (var.mValue != NULL);
      return var;
    }
    

    TRemoteControl::GetReceiveDataVar habe ich nur der Vollständigkeit wegen geposted.

    Wenn ich dann in der Applikation folgendes mache:

    In irgendeinem header:

    RxDataVal mClassNum;
    

    In irgendeiner source:

    RxDataVal mClassNum; 
      mClassNum = mRemoteControl.GetReceiveDataVar (_T("ClassNum"));
      CString s;
      s.Format (_T("%d"), mClassNum);
    

    dann wird die Adresse von RxDataVal.mValue in den String formatiert.

    Wenn ich's so mache:

    s.Format (_T("%d"), DWORD (mClassNum));
    

    dann funktioniert es. Es werden die Daten in den String formatiert.

    Mein Fragen:

    Wie kommt CString::Format an die Adresse des privaten(!) members?

    Ich habe eigentlich erwartet, dass mClassNum durch den operator DWORD () wie eine normale DWORD variable funktioniert. Das scheint aber für die (...) Funktionen nicht zu stimmen oder mache ich noch etwas falsch?

    Herzliche Grüsse
    Walter

    Edit: Copy Paste fehler korrigiert!


  • Mod

    Das Problem ist, dass bei den Elipis (...) für eine Variable Anzahl von Argumenten einfach das Objekt auf den Stack geschoben wird. (D.h. hier nicht Dein gewünschtes DWORD sondern das GANZE Objekt.
    D.h. Format schau nun auf die ersten 4 Bytes auf dem Stack an der Stelle und findet... natürlich Die Daten des Provate-Member.

    Das ist eine Falle. Bei einer Variablen Anzahl von Argumenten musst Du Dir schon ganz sicher sen was Du haben möchtest!

    http://blog.m-ri.de/index.php/2008/01/08/die-unsitte-objekte-direkt-in-printf-und-funktionen-mit-variabler-anzahl-von-argumenten-zu-nutzen/



  • Hallo Martin,

    alles Klar, Danke!

    In der Zwischenzeit habe ich den Rx... und Tx... Klassen eine ToString Methode gespendet.

    Herzliche Grüsse
    Walter


Log in to reply