Problem mit Vererbung und Polymorphie



  • Mir ging auch so etwas, wie bei Nexus durch den Kopf, aber sonst stimme ich Shade zu.



  • Ich sage mal genauer, worum es geht: Ich schreibe ein Musikprogramm:

    Satzzeichen   Tonhoehe
          /    \ /
       Pause   Note
    

    Und ich definiere

    typedef boost::ptr_vector<Satzzeichen> Stimme;
    

    Jetzt will ich herausfinden, ob in einer Stimme die höchste Note (d.h. ignoriere Pausen) mehrfach vorkommt.

    Nexus' Idee wäre ja, der Pause eine Tonhoehe = -10000 zuzuordnen. Geht das eleganter?



  • Mir fällt nur gerade auf, dass die Vererbung

    Tonhoehe
      /
    Note
    

    unklug ist. Eine Note hat eine Tonhöhe, ist aber keine.

    Ich weiss nicht, wie viel eleganter dein Problem gelöst werden kann, ohne Shade Of Mines Vorschlag zu berücksichtigen.

    @ drakon: Das sagt uns nun sehr viel...



  • Hat noch jemand eine andere Idee?


  • Mod

    ich bins schrieb:

    Hat noch jemand eine andere Idee?

    Hör auf Nexus. Dein Problem liegt in vermurkstem Design. Anstatt dies jetzt mit diesem Design irgendwie hinzufrickeln solltest du lieber noch einmal über die Beziehungen zwischen deinen Klassen nachdenken. Wenn das Design gut ist, dann sind dieses und andere Probleme viel einfacher zu lösen.



  • Ich hab ja schon nach Nexus' Kritik meine Vererbungshierarchie geändert. Aber das hat das Problem noch nicht gelöst.



  • Nexus schrieb:

    @ drakon: Das sagt uns nun sehr viel...

    Das soll heissen, dass ich die gleiche Idee schreiben wollte, dann aber gesehen habe, dass du das genau so machst und meinen Post wieder entfernt. Ich hätte auch die gleiche Idee nochmal beschreiben können, was mir aber ein wenig unsinnig erscheint, darum die Zustimmung, dass ich das gleiche vorgeschlagen hätte, aber dass ich grundsätzlich Shades Meinung bin, dass da wohl etwas mit dem Design falsch läuft.



  • Nexus schrieb:

    Eine Note hat eine Tonhöhe, ist aber keine.

    hat vielleicht eine Tonhöhe. Schlagzeugnotation ist da sowas was ziemlich aus der Reihe tanzt. Und in gewissem Maße auch der Generalbass.



  • Wenn das Originaldesign beibehalten werden würde (was ich dir nicht empfehle), könntest du vermutlich sowas basteln:

    bool is_T_derived(const T&) { return true; }
    bool is_T_derived(...) { return false; }
    
    struct Pred
    {
        bool operator<(const U& lhs, const U& rhs)
        {
            if(!is_T_derived(lhs))
                 return is_T_derived(rhs);
            return is_T_derived(rhs) && lhs.tonhoehe < rhs.tonhoehe;
        }
    };
    


  • Inwiefern brauchst du eigentlich die Klasse "Tonhöhe" in deinem Design? Wäre es nicht klüger, wenn du für deine "musikalischen Objekte" (also Noten, Pausen, etc.) eine Methode play() definieren würdest? So hättest du auch gleich die Pausen, Schlagzeugnoten oder was auch immer erschlagen.



  • Du bist viel flexibler, wenn du "spielbare" und "unspielbare" Elemente trennst. Ob du nun eine Midi-Datei generieren willst, das Stück abspielen, den Takt transponieren oder einfach nur nach dem höchsten Ton suchen willst, du musst andauernd die Pausen von den Noten trennen.
    Die Pausen bekommen eine zweite Liste und die dritte Liste ist für Satzzeichen wie Bindebögen, Punktierungen, Generalbass und Text.
    Wenn es dich stört, mehrere Listen zu verwenden, musst du halt einen TonhöhenIterator schreiben, der verdeckt typeof aufruft. Aber das ist mehr Aufwand wie die Trennung der Listen.

    @Michael E.: Rat mal was bei is_T_derived(*(static_cast<Satzzeichen *>(new Tonhoehe()))); passiert.



  • BachfugenFan schrieb:

    @Michael E.: Rat mal was bei is_T_derived(*(static_cast<Satzzeichen *>(new Tonhoehe()))); passiert.

    Was willst du mir sagen? 😕

    error C2440: 'static_cast': 'Tonhoehe *' kann nicht in 'Satzzeichen *' konvertiert werden
    Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.
    

Anmelden zum Antworten