Design-Pattern gesucht: Klasse eines Objekts dynamisch ändern?



  • in deinem beispiel assert(dynamic_cast<bar*>(bar) != 0) das geht gar nicht... bar ist kein zeiger sondern eine klasse, also kann man (bar) nicht caste, weil es gar kein zeiger ist.

    musst mal nochmal genauer ein beispiel geben.



  • Meep Meep schrieb:

    kannst das mal bisschen genauer erklaeren was du da haben willst ? ich blick da nicht ganz durch

    Im Prinzip genau was ich geschrieben habe.

    Vielleicht mal ein ad-hoc Beispiel. Du hast einen Filemanager und liest ein Verzeichnis ein:

    struct document_record
    {
      // file path etc.
    };
    

    Jetzt gehst du die Liste mit document_record* s durch, und änderst jedes *.mpg etc. in

    struct video_document : document_record
    {
      // playtime& stuff
    };
    

    Oder du nimmst das video_document (auch wenn's hier nicht viel Sinn macht) und transformierst es in ein

    struct audio_document : document_record;
    


  • Maxi schrieb:

    in deinem beispiel assert(dynamic_cast<bar*>(bar) != 0) das geht gar nicht... bar ist kein zeiger sondern eine klasse, also kann man (bar) nicht caste, weil es gar kein zeiger ist.

    Ah, danke, kleiner Typo, hab's geändert. frob soll natürlich geändert werden.



  • Das geht so natürlich nicht, jedenfalls nicht mit einem Design Pattern, höchstens mit einem wilden, fragwürdigen Hack über placement-new. Das dem am nächsten kommende Design-Pattern müsste State sein.



  • Bashar schrieb:

    Das geht so natürlich nicht, jedenfalls nicht mit einem Design Pattern, höchstens mit einem wilden, fragwürdigen Hack über placement-new. Das dem am nächsten kommende Design-Pattern müsste State sein.

    Natürlich geht das so nicht, das ist mir klar. Ich wüsste auch nicht wie man das mittels placement-new hacken könnte, ohne wenigstens max(sizeof) irgendwo zu hinterlegen.

    Deswegen suche ich ja nach einem Design-Pattern - wobei Design-Pattern hier für "Design-Pattern" steht, nicht "Design-Pattern aus diesem GOF-Buch".



  • du kannst ja vielleicht sowas in der Art machen:

    class document
    {
        //...
    };
    class video_document:public document
    {
        //...
    };
    class record
    {
        private:
          document* document;
        public:
            setType(document* doc);
            document* getType();  
    };
    transmogrify(record* rec)
    {
         rec->setType(new video_document);
    }
    
    int main()
    {
         record* rec=new record;
         transmogrify(rec);
         assert(dynamic_cast<video_document*>(frob.getType()) != 0);  
    }
    

    muss man natürlich nicht so machen, worauf es ankommt ist halt, dass die arbeit von record an ein polymorphes document weitergeleitet wird. nach aussen hin ändert sich nichts, nach innen is alles möglich 🙂



  • re

    vielleicht einen transmogrify_cast bauen ;o)

    template<class T, class U>
    class IsDerived
    {
       private:
          template<class U>
          class helper
          {
             public:
               typedef char small;
               typedef int big;
    
                static small Test(T);
                static big Test(...);
                static U* MakeT(void);
          };
    
          typedef helper<U> my_helper;
    
       public:
          enum { result = (sizeof(my_helper::Test(*my_helper::MakeT())) ==
                          sizeof(my_helper::small)) };
    
    };
    
    template<class T, class U>
    int is_derived(const U &param)
    {
       return IsDerived<T*,U>::result;
    }
    
    template<int b>
    class bool_type { };
    
    template<class T, class U>
    bool MakeNewType(U *&u, typename bool_type<0> b)
    {
       return false;
    }
    
    template<class T, class U>
    bool MakeNewType(U *&u, typename bool_type<1> b)
    {
       U *t_u = new T(*u);
       delete u;
       u = t_u;
       return true;
    }
    
    template<class T, class U>
    bool transmogrify_cast(U *&u)
    {
       return MakeNewType<T>(u, bool_type<IsDerived<T,U>::result>());
    }
    
    struct base
    {
       base(void) { }
       base(const base &b) { }
       virtual const char* ausgabe(void) const
       {
          static const char buf[] = "bin ein base";
          return buf;
       }
    };
    
    struct foo : base
    {
       foo(void) { }
       foo(const base &b) : base(b) { }
       virtual const char* ausgabe(void) const
       {
          static const char buf[] = "bin ein foo";
          return buf;
       }
    };
    
    struct bar : base
    {
       bar(void) { }
       bar(const base &b) : base(b) { }
       virtual const char* ausgabe(void) const
       {
          static const char buf[] = "bin ein bar";
          return buf;
       }
    };
    
    TFMain *FMain;
    
    __fastcall TFMain::TFMain(TComponent* Owner) : TForm(Owner)
    {
       this->Color = static_cast<TColor>(0xD8D8D8);
    
       base *p = new foo;
       ShowMessage(p->ausgabe());
       transmogrify_cast<bar>(p);
       ShowMessage(p->ausgabe());
       delete p;
    }
    

    Ausgabe:
    bin ein foo
    bin ein bar

    Meep Meep



  • es ist technisch nicht möglich einfach die klase eines objektes zu ändern

    da du allerdings dynamisch in subklassen transformieren willst, kannst du evtl einfach das objekt austauschen

    alternativ kannst du auch die metadata policy als membervariable der dateien machen, und dann kannst du je nach erkannten typ einfach das member setzen

    pfad datei("C:\\test.txt");
    datei.typinformationen = text_datei_infos(datei);
    


  • So ganz ist die GoF aber auch nicht aus dem Rennen

    "Brücke" ("Bridge") (liegt machen Vorschlägen zugrunde) und "Zustand" ("State"); zu letzterem schreiben Gamma et al.

    "Zweck:[...] Es wird so aussehen, als ob das Objekt seine Klasse gewechselt habe"
    (4. korrigierter deutscher Nachdruck Addison-Wesley 1996 S.398)

    Grüsse

    *this



  • @finix: Da das was du suchst so nicht möglich ist wäre es doch hilfreich zu wissen was genau du machen willst.
    Es gibt mehrere Möglichkeiten so etwas ähnliches zu machen, aber ohne genau zu wissen welche Eigenschaften du wirklich benötigst und welche nicht kann man wohl nur einen Schuss ins Blaue machen, und dafür ist mir irgendwie meine Zeit zu schade.

    EDIT: die einfachste Variante wäre ein Zeiger auf einen Zeiger.


Anmelden zum Antworten