Design Problem



  • Hallo zusammen,

    ich habe ein kleines Design Problem und würde gerne einmal eure Meinung dazu wissen. Unten stehender code zeigt etwas vereinfacht mein Problem.
    Im Großen und Ganzen habe ich zwei Klass designt, eine container Klasse und eine Dialog Klasse die ich in diesem container plazieren kann (Das ist so ne Art MDI Anwendung innerhalb von Dialogen).
    Jetzt möchte ich davon ableiten und z.B. eine Funktion "foo" aus CMyBetterDialog aufrufen. Müsste also in meiner Klass immer von CMyDialog zu CMyBetterDialog downcasten. (ist hässlich, lässt sich aber wohl nicht vermeinden) Also überdecke ich die "addDialog" Methode der basisklasse um zu verhindern, dass CMyDialog objekte geadded werden.
    Jetzt kann man aber natürlich immer noch z.B. mit einem CMyContainer pointer auf die alte "addDialog" methode zugreifen.

    Nun zu meiner Frage:
    Wäre in diesem Falle der Benutzer der Klasse selbst Schuld oder ist das hier vielleicht wirklich ein schwerer Designfehler von mir?
    In C++ kann man mittels statischer casts ja leider alles machen. Da hilft auch keine privates ableiten 🙄

    class CMyDialog;
    class CMyBetterDialog;
    
    class CMyContainer
    {
    public:
      void addDialog(CMyDialog* dialog);
    
    private:
      CArray<CMyDialog*> m_dialogs;
    };
    
    class CMyBetterContainer : private CMyContainer
    {
      void addDialog(CMyBetterDialog* dialog);
    };
    
    class CMyDialog
    {
    public:
      CMyDialog(CMyContainer* parent);
    
    private:
      CMyContainer *m_container;
    };
    
    class CMyBetterDialog : private CMyDialog
    {
    public:
      CMyBetterDialog(CMyBetterContainer* parent);
      void foo();
    
    };
    


  • Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum MFC (Visual C++) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Die Frage lässt sich so gar nicht beantworten, weil nicht bekannt ist, was foo zu welcher Zeit machen soll.

    Und wenn es dich stört, dann ist Ableitung hier einfach total falsch und du musst auf Komposition zurückgreifen.

    Die Klassen nutzen dann noch die Basisklassen, aber es sind selber keine Instanzen mehr davon.

    class CMyBetterContainer
    {
     CMyContainer *mConti;
    
     CMyBetterContainer()
     {
      // mConti neu erzeugen oder als Parameter übergeben...
     }
    
     void addDialog(CMyBetterDialog* dialog)
     {
      mConti->addDialog(dialog);
     }
    };
    
    class CMyBetterDialog
    {
    public:
      CMyBetterDialog(CMyBetterContainer* parent);
    
      void foo();
    
    };
    

    Und bitte lass dieses C vor dem Klassennamen weg. Wir befinden uns mittlerweile schon im Jahr 2012 🙄



  • Danke für die Antwort. Ich arbeite leider mit der mfc und da ist das ja Konvention.
    Eigentlich würde ich schon meinen dass ich ableiten muss. Meine abgeleitete klasse IST ein Dialog und HAT keines. Aber die downcasts sind schon ein Indikator für ein falsches Design 🙄 Da gebe ich dir recht.



  • Habe gerade einen witzigen Artikel zum Thema C prefix gelesen.
    http://www.jelovic.com/articles/stupid_naming.htm


  • Mod

    Ich verstehe Dein Problem nicht. Wer will foo aufrufen?
    Wenn es eine Klasse außerhalb ist und die auf CMyBetterDialog angeweiesen ist dann musst Du einen downcast verwenden logisch. Dafür hat die MFC DYNAMIC_DOWNCAST oder dynamic_cast im C++ Syntax. Und die sind entsprechend sicher.

    Wenn fo aus CMyContainer aufgerufen werden muss dann ist das sicher, denn die Klasse weiß ja, dass sie nur CMyBetterDialog bekommen hat undkann den doencast intern auch verstecken. in einer Fuktion die getDialog (o.ä.) und den entsprechenden Zeiger zurück gibt.
    Du benötigst also den downcast nur an einer Stelle und diese Klasse weiß ja was sie bekommen hat, auch wenn sienur Zeiger auf CMyDialog speichert.

    Gehört foo in alle Dialoge dann gehört die Funktion virtuell nach CMyDialog!



  • Das Problem ist folgendes:
    Ich habe zwei Klasse, Container und Dialog die miteinander kommunizieren. Ich habe also eine Bidirektionale Assoziation (1:m). Jetzt will ich von beiden Klassen ableiten (also z.B. BetterContainer, BetterDialog). Diese beiden Klassen müssen ebenfals miteinander kommunizieren, aber über das interface, dass die beiden abgeleiteten Klassen zur Verfügung stellen. Ich muss also in BetterContainer und in BetterDialog immer die Container und Dialog pointer downcasten.
    Finde ich irgendwie unschön und das Klassendiagramm sieht irgendwie auch komisch aus:
    Container <------------------------> Dialog
    ^ ^
    | |
    BetterContainer <-------------> BetterDialog

    Will aber keine Komposition verwenden da dann das messagerouting nicht mehr richtig funktioniert (müsste dann über notify messages gehen).



  • Was kommunzieren die Elternklassen miteinander? Darf es sowieso nur immer passende "Pärchen" geben (BetterContainer mit BetterDialog, AnotherBetterContainer mit AnotherBetterDialog) geben? Falls ja, könntest Du auch aus Container und Dialog ein Template machen und brauchst gar keine Vererbung einsetzen.

    Zu Deiner anderen Frage, ob der Anwender Schuld sei, wenn er nicht darauf achtet addDialog immer an den abgeleiteten Versionen aufzurufen: Nein, ich denke er wäre nicht Schuld. IMHO ist es ein elemantares Feature von Vererbung, dass sowas korrekt funktionieren sollte. Jeder, der es vielleicht doch übersieht, würde vermutlich lange damit zubringen, den "Bug" zu suchen und Dich hinterher verfluchen. 😉


Anmelden zum Antworten