Öffentliche Methoden von Basisklasse privat in abgeleiteter Klasse machen



  • Hallo.

    Eine abgeleitete Klasse redefiniert zwei Methoden die öffentlich sind (auch in der Basis sind die öffentlich). Nun möchte ich, dass der Benutzer meiner Klasse nur die redefinierten Methoden aufrufen darf, nicht aber die der Basisklasse!

    Hier ein wenig Code: Die abgeleitete Klasse:

    class Limited_list : public List {
    	public:
    		Limited_list(uint32& weight, const uint32& weight_limit);
    		virtual ~Limited_list();
    
                    //Beide Methoden werden redefiniert
    		virtual bool insert(const Item* item, int32 amount=1); 
    		virtual void remove(const Item* item, int32 amount=1);
    	private:
    		uint32& curr_weight_;
    		const uint32& weight_limit_;
    
    		Limited_list(const Limited_list&);
    		Limited_list& operator=(const Limited_list&);
    };
    

    Der Benutzer darf folgendes nicht machen:

    Limited_list ll(...);
    ll.List::insert(...); //darf er nicht
    ll.insert(...); //darf und soll er
    

    Ich hab versucht, sowohl List::insert als auch -remove mit der using-Direktive in private sichtbar zu machen, was aber nicht funktioniert hat 😞

    Weiss jemand, wie's geht?



  • Hi,

    versuch es mal so:

    class Limited_list : protected List
    {
       .
       . 
       .
    };
    

    Gruss



  • Moment!

    Mit protected kenne ich mich nicht aus, aber wird dann nicht alles privat vererbt?
    Ich hab da nämlich noch viel mehr als zwei Funktionen, die aber öffentlich bleiben sollen!



  • Nun möchte ich, dass der Benutzer meiner Klasse nur die redefinierten Methoden aufrufen darf, nicht aber die der Basisklasse!

    Wenn du jetzt ausschließlich sowas meinst

    ll.List::insert(...); //darf er nicht
    

    dann würde ich sagen, ist das ein user-Fehler. Da würde ich mir keine Gedanken machen.
    Wenn du schon netterweise eine dynamisch gebundene Methode anbietest, dann darf der Benutzer der Klasse halt nicht zu blöd sein, sie richtig zu benutzen.



  • Hmm. OK. Dann muss ich mich auf den Benutzer 'verlassen'.

    Danke euch beiden!



  • Allerdings kann es evtl. Sinn machen, sowas zu designen:

    - List
    - UnlimitedList : public List
    - LimitedList : public List

    wo 'List' praktisch nur abstrakte Methoden als Schnittstelle bereit stellt.

    LimitedList implementiert die dann anders als UnlimitedList und die Methode von der Basisklasse kann auch nicht aufgerufen werden, wenn sie abstrakt ist.
    LimitedList kann dann auch noch die Schnittstelle erweitern um getLimit() oder sowat.

    Ja, das gefällt mir fast noch besser. Hängt aber vielleicht auch von deinem Anwendungsfall ab.



  • Wie EarlyBird schon gesagt hat, musst Du eine protected oder private-Vererbung durchführen und alle Methoden der Basisklasse, die aber trotzdem noch öffentlich benutzt werden sollen, noch mal neu aufführen.

    class Limited_list : private List {
        public:
            Limited_list(uint32& weight, const uint32& weight_limit);
            virtual ~Limited_list();
    
                    //Beide Methoden werden redefiniert
            virtual bool insert(const Item* item, int32 amount=1); 
            virtual void remove(const Item* item, int32 amount=1);
            List::Methode1; // nach diesem Schem hier alle Methoden von List aufführen, welche der Benutzer trotz private-Vererbung trotzdem aufrufen darf
        private:
            uint32& curr_weight_;
            const uint32& weight_limit_;
    
            Limited_list(const Limited_list&);
            Limited_list& operator=(const Limited_list&);
    };
    


  • mir fällt da eigentlich spontan das Template Method Design Pattern ein...



  • Hey, das klingt klasse!

    Die Klasse List stellt allerdings essenzielle Implementierungen bereit, die dann explizit von Limited_list innerhalb der redefinierten Funktionen aufgerufen und abgearbeitet werden. Insofern müsste ich der von dir vorgeschlagenen abstrakten Klasse List eine Default-Implementation bereitstellen. Will die nämlich nicht zweimal schreiben (für die un- und limited variationen).

    Diese Default-Implementation wird allerdings protected sein, sonst wird sich am Benutzer-Problem rein gar nichts geändern haben. 🙂

    Auch wenn ich deine Idee, Optimizer, nicht umsetzen werde (wenig Zeit und faul), so find ich die Überlegung doch sehr gut.



  • Monastero schrieb:

    Wie EarlyBird schon gesagt hat, musst Du eine protected oder private-Vererbung durchführen und alle Methoden der Basisklasse, die aber trotzdem noch öffentlich benutzt werden sollen, noch mal neu aufführen.

    class Limited_list : private List {
        public:
            Limited_list(uint32& weight, const uint32& weight_limit);
            virtual ~Limited_list();
      
                    //Beide Methoden werden redefiniert
            virtual bool insert(const Item* item, int32 amount=1); 
            virtual void remove(const Item* item, int32 amount=1);
            List::Methode1; // nach diesem Schem hier alle Methoden von List aufführen, welche der Benutzer trotz private-Vererbung trotzdem aufrufen darf
        private:
            uint32& curr_weight_;
            const uint32& weight_limit_;
    
            Limited_list(const Limited_list&);
            Limited_list& operator=(const Limited_list&);
    };
    

    Sind zu viele Funktionen, die 'neu aufgeführt' werden müssen. Die Basisklasse ist sehr gross. Optimizers Überlegung find ich besser, trotzdem danke.


Anmelden zum Antworten