Bug (?): Property als Referenz



  • Hallo,

    der C++ Compiler im Borland Developer Studio hat anscheinend ein Problem mit Properties, die eine Referenz zurückgeben. Allerdings nicht immer. Beispielprogramm:

    // Version information:
    // Borland® Developer Studio für Microsoft® Windows™ Version 10.0.2166.28377 Update 1  
    
    #include <iostream.h>
    #pragma hdrstop
    
    class InnerClass
    {
      public:
        void AFunction(int Parameter) { cout << Parameter << endl; }
    };
    
    class OuterClass
    {
      public:
        OuterClass(){}   // compiler wants to have a user-defined constructor
        InnerClass InnerObject;
        InnerClass& ReadInnerObject() { return InnerObject; }
        __property InnerClass& AProperty = { read = ReadInnerObject };
    };
    
    #pragma argsused
    int main(int argc, char* argv[])
    {
      OuterClass OuterObject;
    
      OuterObject.ReadInnerObject().AFunction(42);    // prints 42
      OuterObject.AProperty.AFunction(43);            // prints 1
      OuterObject.ReadInnerObject().AFunction(44);    // prints 44
      InnerClass& ref = OuterObject.InnerObject;
      ref.AFunction(45);                              // prints 45
    
      char c;       // wait
      cin >> c;
    }
    

    Weiß jemand etwas näheres darüber, wie sich dieser Bug (sofern es einer ist) beseitigen läßt? (Daß es Workarounds gibt, ist mir klar, siehe den Code.)

    Danke,
    Martin



  • Hallo

    das ist kein Fehler vom Builder. Der eintige Fehler ist, das es keine Warnung ausspuckt, weil du eine Referenz auf eine lokale Variable zurückgibst. Deshalb kommt es zu undefiniertem Verhalten und du kannst froh sein, das du überhaupt eine Ausgabe bekommst und keine Zugriffsverletzung.

    Um dein Programm korrekt auszuführen, must du das mit Pointern machen

    // Version information:
    // Borland® Developer Studio für Microsoft® Windows™ Version 10.0.2166.28377 Update 1  
    
    #include <iostream.h>
    #pragma hdrstop
    
    class InnerClass
    {
      public:
        void AFunction(int Parameter) { cout << Parameter << endl; }
    };
    
    class OuterClass
    {
      public:
        OuterClass(){}   // compiler wants to have a user-defined constructor
        InnerClass InnerObject;
        InnerClass* ReadInnerObject() { return &InnerObject; }
        __property InnerClass* AProperty = { read = ReadInnerObject };
    };
    
    #pragma argsused
    int main(int argc, char* argv[])
    {
      OuterClass OuterObject;
    
      OuterObject.ReadInnerObject()->AFunction(42);    // prints 42
      OuterObject.AProperty->AFunction(43);            // prints 1
      OuterObject.ReadInnerObject()->AFunction(44);    // prints 44
      InnerClass& ref = OuterObject.InnerObject;
      ref.AFunction(45);                              // prints 45
    
      char c;       // wait
      cin >> c;
    }
    

    bis bald
    akari



  • Hallo akari,

    vielen Dank für Deine Antwort. Selbige solltest Du aber besser nochmals gründlich überdenken. Entschuldige bitte.

    Martin



  • Hallo

    In welcher Beziehung? Meine Veränderung am Code läßt diesen fehlerfrei ablaufen.

    Allerdings ist meine Begründung wohl Unsinn, offenbar kommen die Properties wirklich nicht mit Referenzen zurecht.

    bis bald
    akari



  • akari schrieb:

    In welcher Beziehung? Meine Veränderung am Code läßt diesen fehlerfrei ablaufen.

    Das muß aber nicht so bleiben. Immerhin gibst du hier einen Pointer auf ein lokales Objekt (in diesem Fall Klassenmember) zurück. Falls die Klasseninstanz ungültig wird, wird das dein Pointer auch. Hier ist wohl eher eine Kopie angesagt.



  • vergiss das mit __property mal wieder ganz schnell. damit baust du dir nur unportierbaren code und unnötigen overhead zusammen!

    schon gar nicht würde ich borland-spezifische sachen mit konsolen-anwendungen vermischen!



  • Sehe ich auch so.
    Außerdem sollte man das hier

    #include <iostream.h>
    

    durch das hier ersetzen

    #include <iostream>
    

    Dann wird es standardkonformer. Evtl. ist dann oben noch ein

    using namespace std;
    

    angebracht oder ein std:: vor den entsprechenden Bezeichnern (cout, cin, endl).


Anmelden zum Antworten