Abstrakte Klasse



  • Hey Leute.
    Mal so ne frage zu Abstrakten Klassen , ich komm mal auf den Punkt 😃 .

    Also ich weiß das wen eine Klasse nur eine Abtrakte Methode enthält abtrakt ist und so mit von dieser kein Objekt mehr erzeugt werden kann:
    Abstracte Methode:

    void Funktion() = 0;
    

    Somit sieht eine Abstrakte Klasse ja so aus:

    class AbstrakteKlasse
    {
    public:
       void Funktion1 = 0;
       void Funktion2 = 0;
       void Funktion3 = 0;
    };
    

    1.) Die Klasse die von ihr erbt ist dan auch abstrakt, wenn nicht alle abstrakten Methoden redefieniert werden oder?

    2.)Müssen alle Elemente dieser Klsse abstract sein?

    3.)Kann auch der Konstruktor Abstrakt sein?

    4.)Kann man in dieser Klasse auch Eigenschaften mit übergeben?
    Wie z.b bei den stream klassen wird ja auch ein enum aus "ios" benutzt, die eigentlich abstrakt ist.

    5.) Wo liegt der sinn dieser abstracten Klassen?

    6.) Wie wände ich diese sinnvoll an?

    Mfg Wikinger75!



  • 1. ja
    2. nein
    3. nein
    4. ja
    5. Schnittstellenvorgabe. Damit man Objekte solcher Klassen Instanzieren können soll, muß jemand die Methoden implementieren. Normalerweise heißt eine abstrakte Klasse soviel wie "Ich weiß nur was ich für Methoden brauche, aber was da drin stehen soll, weiß ich nicht. Also macht das jemand anderes."
    6. Siehe 5.



  • Wikinger75 schrieb:

    ...
    6.) Wie wände ich diese sinnvoll an?

    Mfg Wikinger75!

    Mit "e". 😉

    Also mal im Ernst: Die dahinter ist, verschiedene Klassen auf gleiche Eigenschaften zurückzuführen.

    struct Base {
       virtual void f() = 0;
    };
    
    struct D1 : Base {
       void f() { cout << "tue dies\n"; }
    };
    
    struct D2 : Base {
       void f() { cout << "tue das\n"; }
    };
    
    void allgemeineFunktion(Base*  b) {
       // Diese Funktion braucht nicht zu wissen, welche Klasse genau 
       // dahintersteckt; nur, dass sie von Base abstammt
       b->f();
    }
    
    int main() {
       D1 d1;
       D2 d2;
    
       allgemeineFunktion(&d1);
       allgemeineFunktion(&d2);
       return 0;
    }
    

    1.) Die Klasse die von ihr erbt ist dan auch abstrakt, wenn nicht alle abstrakten Methoden redefieniert werden oder?

    Jap.

    2.)Müssen alle Elemente dieser Klsse abstract sein?

    Nein.
    Es können sowieso nur Funktionen virtuell sein und man nennt die "Elemente" auch nicht "abstrakt" (das betrifft die Klasse), sondern "pure virtual".

    3.)Kann auch der Konstruktor Abstrakt sein?

    Ich sehe keine Veranlassung das zu tun ... vor allem, weil Konstruktoren nicht virtuell sind (= nicht überladen werden können).

    4.)Kann man in dieser Klasse auch Eigenschaften mit übergeben?

    Ja - ist eine ganz normale Klasse; nur, dass man sie nicht instantiieren kann.

    Gruß,

    Simon2.



  • Danke für eure Antworten Leute^^



  • Ähm ja nächste frage^^

    wenn ich z.b das mache:

    class Attribute
    {
        private:
        std::string Value;
        public:
        void setValue() = 0;
    };
    

    Dann ich ja in der Klasse wo die Methode redefeniert wird nicht mehr auf Value zugreifen. Währe es hier nicht sinvoll Value als protected zu dekladieren?

    Mfg Wikinger75!


  • Administrator

    Dein Beispiel ist unsinnig. Wieso sollte setValue abstrakt sein, wenn der Wert, welcher gesetzt wird, in Attribute liegt? Vielleicht suchst du eher sowas?

    class Attribute
    {
    private:
      std::string vm_alue;
    
    protected:
      virtual void on_value_changed() { }
    
    public:
      void set_value(std::string const& value)
      {
        m_value = value;
    
        on_value_changed();
      }
    };
    

    Ich würde aber on_value_changed nicht abstrakt machen. Erscheint mir auch unsinnig.

    Grüssli



  • Wikinger75! Hast du meine Antwort unter 5. nicht gelesen? Du hast mit dem string-Attribut doch gegen den eigentlichen Grund der abstrakten Klasse gehandelt, und wusstest anscheinend doch, was da rein gehört. Also warum hast du die Methode setValue nicht implementiert? Wenn du setValue nicht kennst, kennst du logischerweise auch Value nicht.



  • @Dravere
    Hmm währe so auch gut...

    @Bulli

    Wikinger75! Hast du meine Antwort unter 5. nicht gelesen? Du hast mit dem string-Attribut doch gegen den eigentlichen Grund der abstrakten Klasse gehandelt, und wusstest anscheinend doch, was da rein gehört. Also warum hast du die Methode setValue nicht implementiert? Wenn du setValue nicht kennst, kennst du logischerweise auch Value nicht.

    Ja, aber mit einer Abstracten Klasse gibt man ja eine schablone vor und alle die von dieser Schablone erben sollen ein Value atribut enthalten, wenn ich dieses ja aber nicht in der absrtacten klasse erwähne, werden die anderen Klassen nicht dazu verdonert dieses zu besitzen.
    SetValue abstract zu machen ist unsinig das stimmt, aber es soll kein Objekt von dieser Klasse erzeugt werden können!

    Es gibt hier also zwei möglichkeiten.

    1.) Value wird protected und setValue abtract, damit es überschrieben werden muss und man auf Value noch so zugreifen kann.

    2.) Value wird privat und setValue wird als eine normale methode impementiert, jedoch wie kann ich dan verhindern, dass man davon kein objekt erzeugen kann?

    Obwohl mir wird auch grade Klar das es unötig ist die klasse als abstract zu machen, da es sinvoll währe, das ich einen Zeiger von der Basisklasse machen kann und so auf die anderen Objekte der vererbten Klassen zugreifen kann.

    Mfg Wikinger75!


  • Administrator

    class VonMirKannManKeinObjekteHerstellen
    {
    protected:
      VonMirKannManKeinObjekteHerstellen()
      {
      }
    };
    

    Mach den Konstruktor protected. So können davon abgeiltete Klassen erstellt werden, aber man kann die Basis selber nicht kontruieren. Für sowas braucht man keine abstrakte Klasse.

    Grüssli



  • Wikinger75 schrieb:

    jedoch wie kann ich dan verhindern, dass man davon kein objekt erzeugen kann?

    Destructor pure virtual machen. Allerdings musst du trotzdem noch eine Implementierung des Dtor bereitstellen weil der dann von den Dtoren der abgeleiteten Klassen aufgerufen wird.
    In einigen Codingstyles wird vorgeschlagen/verlangt, dass bei abstrakten Klassen grundsätzlich auch der Dtor pur virtuell gekennzeichnet wird - aus verschiedenen Gründen.





  • pumuckl schrieb:

    Destructor pure virtual machen. Allerdings musst du trotzdem noch eine Implementierung des Dtor bereitstellen weil der dann von den Dtoren der abgeleiteten Klassen aufgerufen wird.

    Ist das nicht ein wenig widersprüchlich? Rein virtuell sollte meines Erachtens eine Funktion gemacht werden, die erst in abgeleiteten Klassen implementiert wird.

    Was spricht denn gegen einen protected -Konstruktor?



  • Nexus schrieb:

    Ist das nicht ein wenig widersprüchlich? Rein virtuell sollte meines Erachtens eine Funktion gemacht werden, die erst in abgeleiteten Klassen implementiert wird.

    Rein virtuell heißt nicht dass man nicht ne default-Implementierung zur Verfügung stellen kann. Es heißt nur dass sie in abgeleiteten Klassen explizit implementiert werden muss. Und das macht beim Dtor im Zweifel ja der Compiler für uns.

    Was spricht denn gegen einen protected -Konstruktor?

    Folgendes:

    class Base //sollte abstrakt sein
    {
    protected:
      Base() {}
    };
    
    class Derived : public Base
    {
    private: //Instanzbildung verhindern
      Derived();
      Derived(Derived const&);
      ~Derived();
    public:
      static Base* makeBase() 
      {
        cout << "Und die Moral von er Geschicht:\nProtected Ctor macht die Klasse abstract nicht." << endl;
        return new Base;
      } 
    };
    


  • pumuckl schrieb:

    In einigen Codingstyles wird vorgeschlagen/verlangt, dass bei abstrakten Klassen grundsätzlich auch der Dtor pur virtuell gekennzeichnet wird - aus verschiedenen Gründen.

    "Grundsätzlich" ist spätestens mit COM relativiert.

    Nexus schrieb:

    Ist das nicht ein wenig widersprüchlich? Rein virtuell sollte meines Erachtens eine Funktion gemacht werden, die erst in abgeleiteten Klassen implementiert wird.

    Wenn man eine Klasse mit einem abstract -Keyword entsprechend attribuieren könnte, dann wäre der Kunstgriff der rein virtuellen Funktionen mit Default-Implementierung nicht notwendig gewesen. Aber dafür hätte man ja ein zusätzliches Schlüsselwort gebraucht :p



  • pumuckl schrieb:

    Rein virtuell heißt nicht dass man nicht ne default-Implementierung zur Verfügung stellen kann. Es heißt nur dass sie in abgeleiteten Klassen explizit implementiert werden muss. Und das macht beim Dtor im Zweifel ja der Compiler für uns.

    Ja, das schon. Aber abgesehen vom Destruktor ist das sowieso irrelevant, da bei abgeleiteten Klassen nicht automatisch die Basisklassenversion der Funktion aufgerufen wird.

    pumuckl schrieb:

    Und die Moral von er Geschicht: Protected Ctor macht die Klasse abstract nicht

    Aber es ging doch darum, die Instanziierung von aussen zu verhindern? Dass diese innerhalb abgeleiteter Klassen möglich ist, tut ja nichts zur Sache...

    audacia schrieb:

    Aber dafür hätte man ja ein zusätzliches Schlüsselwort gebraucht :p

    Du spielst wohl auf das Recycling an? 😉

    Ich sehe die Idee hinter dem "Hack" nicht ganz. Warum soll eine Klasse abstrakt sein, nur damit sie selber nicht instanziierbar ist, aber abgeleitete Klassen es automatisch sind? Meistens braucht man rein virtuelle Funktionen im Zusammenhang mit einer Funktionalität, die die Basisklasse aufgrund mangelnder Spezialisierung noch nicht hat.



  • Nexus schrieb:

    pumuckl schrieb:

    Und die Moral von er Geschicht: Protected Ctor macht die Klasse abstract nicht

    Aber es ging doch darum, die Instanziierung von aussen zu verhindern? Dass diese innerhalb abgeleiteter Klassen möglich ist, tut ja nichts zur Sache...

    Nur als Bestandteil abgeleiteter Klassen, ja. Abstrakt heißt es darf keine alleinstehenden Objekte der Klasse geben. Genau das ist in meinem Beispiel oben aber möglich - mit pur virtuellen Methoden aber nicht.



  • Wikinger75 schrieb:

    Ja, aber mit einer Abstracten Klasse gibt man ja eine schablone vor und alle die von dieser Schablone erben sollen ein Value atribut enthalten, wenn ich dieses ja aber nicht in der absrtacten klasse erwähne, werden die anderen Klassen nicht dazu verdonert dieses zu besitzen.
    SetValue abstract zu machen ist unsinig das stimmt, aber es soll kein Objekt von dieser Klasse erzeugt werden können!

    Nein, du hast es leider nicht verstanden. Woher willst du wissen, das der Implementierer der Schnittstelle ein Value-Attribut braucht??? Du weißt es nicht! Du kannst eine Default-Implementierung anbieten, aber dann ist es nicht mehr abstrakt, sondern deine Methode nur virtuell (nicht pur virtual).

    Mit abstrakten KLassen gibts du die Schnittstelle vor, Punkt!

    Denn was ist, wenn der Implementierer keinen Value haben will, sondern den Wert z.B. von einem Server holt?

    class Base
    {
        public:
           virtual void setValue(int) = 0;
           virtual int getValue() = 0;
    };
    
    class Special : public Base
    {
        Server server;
        public:
          void setValue(int a)
          {
                server.set(a);
          }
    
          int getValue()
          {
                return server.get();
          }
    };
    

    In dem obigen Beispiel wäre dein Value-Attribut arbeitslos und das fünfte Rad am Wagen. Niemand nutzt es, es verbraucht Speicherplatz und wird andere Benutzer die den Source warten sollen, verwirren.

    Wenn du es besser weißt, als der Implementierer, dann mach es nicht pur virtual! Sondern nur virtual.



  • pumuckl schrieb:

    Nur als Bestandteil abgeleiteter Klassen, ja. Abstrakt heißt es darf keine alleinstehenden Objekte der Klasse geben. Genau das ist in meinem Beispiel oben aber möglich - mit pur virtuellen Methoden aber nicht.

    Hmm, das stimmt natürlich. Aber ich dachte, es ginge Wikinger75 bei seiner Frage grundsätzlich darum, die Instanziierung eines Objekts von aussen zu verbieten.

    Wie gesagt kommt mir das Vorgehen aber von Grund auf eher merkwürdig vor, da ich eigentlich immer den Fall hatte, in dem eine Basisklasse nicht instanziiert werden sollte, weil sie noch kein konkretes Objekt repräsentiert. Wenn alle Funktionen bereits fest stehen, ist das Objekt für mich konkret. Ein künstliches Abstrakt-Machen durch einen rein virtuellen, aber doch implementierten Destruktor scheint mir der falsche Ansatz zu sein...



  • pumuckl schrieb:

    ..."Und die Moral von er Geschicht:\nProtected Ctor macht die Klasse abstract nicht."...

    😃 😃 😃 😃 🤡 👍

    Das werde ich so schnell nicht vergessen => Didaktik 1,0

    Gruß,

    Simon2.


Anmelden zum Antworten