<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Vererbung Funktionalität erweitern]]></title><description><![CDATA[<p>Folgende Frage zum Design einer Anwendung:</p>
<p>Ich habe eine Klassenhierarchie, bei der ich die Daten der einzelnen Objekte mithilfe einer Funktion (readAttributes) setze. Also in etwa so:</p>
<pre><code class="language-cpp">class Base{
 public:
  virtual void readAttributes(Attriubtes* data){
   // setze Membervariablen von Base entsprechend der Werte in Data
  }
}
</code></pre>
<p>Wenn ich jetzt die Attribute für ein abgeleitetes Objekt erstellen möchte, müssen natürlich auch die Daten des übergeordneten Objekts gesetzt werden. D.h., die Abgeleitete Klasse macht folgendes:</p>
<pre><code class="language-cpp">class Derived:public Base{
 public:
  virtual void readAttributes(Attriubtes* data){
   Base::readAttributes(data);
   // setze Membervariablen von Base entsprechend der Werte in Data
  }
}
</code></pre>
<p>Im Prinzip funktionier diese Implementierung, nur finde ich es etwas unschön, dass in jeder abgeleiteten Klasse explizit die Funktion der Basisklasse aufgerufen werden muss (da man dass auch recht einfach vergessen kann^^).</p>
<p>Daher meine Frage:<br />
Gibt es vielleicht eine Möglichkeit, die &quot;eleganter&quot; zu lösen, insbesondere, da dieses Beispiel nicht die einzige Gruppe von Funktionen ist, bei denen ein derartiges Verhalten notwendig ist, sodass eine allgemeine Lösung recht hilfreich wäre.</p>
<p>Im Prinzip ist es ja so, ich habe die Funktion als virtuelle Funktion, was ja heißt, dass die abgeleitete Klasse eine völlig neue Funktionalität zur Verfügung stellen kann. Was ich aber tatsächlich möchte, ist, dass die abgeleitete Klasse die Funktionalität der Basisklasse erweitert. Ausspalten in zwei Methoden (eine virtuelle, protected und eine nicht virtuelle public) ist aufgrund der Tiefe der Klassenhierarchie auch nicht sinnvoll (bis 5 ebenen).</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/262160/vererbung-funktionalität-erweitern</link><generator>RSS for Node</generator><lastBuildDate>Sun, 06 Sep 2026 18:46:24 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/262160.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 01 Mar 2010 20:17:39 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Vererbung Funktionalität erweitern on Mon, 01 Mar 2010 20:17:39 GMT]]></title><description><![CDATA[<p>Folgende Frage zum Design einer Anwendung:</p>
<p>Ich habe eine Klassenhierarchie, bei der ich die Daten der einzelnen Objekte mithilfe einer Funktion (readAttributes) setze. Also in etwa so:</p>
<pre><code class="language-cpp">class Base{
 public:
  virtual void readAttributes(Attriubtes* data){
   // setze Membervariablen von Base entsprechend der Werte in Data
  }
}
</code></pre>
<p>Wenn ich jetzt die Attribute für ein abgeleitetes Objekt erstellen möchte, müssen natürlich auch die Daten des übergeordneten Objekts gesetzt werden. D.h., die Abgeleitete Klasse macht folgendes:</p>
<pre><code class="language-cpp">class Derived:public Base{
 public:
  virtual void readAttributes(Attriubtes* data){
   Base::readAttributes(data);
   // setze Membervariablen von Base entsprechend der Werte in Data
  }
}
</code></pre>
<p>Im Prinzip funktionier diese Implementierung, nur finde ich es etwas unschön, dass in jeder abgeleiteten Klasse explizit die Funktion der Basisklasse aufgerufen werden muss (da man dass auch recht einfach vergessen kann^^).</p>
<p>Daher meine Frage:<br />
Gibt es vielleicht eine Möglichkeit, die &quot;eleganter&quot; zu lösen, insbesondere, da dieses Beispiel nicht die einzige Gruppe von Funktionen ist, bei denen ein derartiges Verhalten notwendig ist, sodass eine allgemeine Lösung recht hilfreich wäre.</p>
<p>Im Prinzip ist es ja so, ich habe die Funktion als virtuelle Funktion, was ja heißt, dass die abgeleitete Klasse eine völlig neue Funktionalität zur Verfügung stellen kann. Was ich aber tatsächlich möchte, ist, dass die abgeleitete Klasse die Funktionalität der Basisklasse erweitert. Ausspalten in zwei Methoden (eine virtuelle, protected und eine nicht virtuelle public) ist aufgrund der Tiefe der Klassenhierarchie auch nicht sinnvoll (bis 5 ebenen).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1862972</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1862972</guid><dc:creator><![CDATA[ngc92]]></dc:creator><pubDate>Mon, 01 Mar 2010 20:17:39 GMT</pubDate></item><item><title><![CDATA[Reply to Vererbung Funktionalität erweitern on Mon, 01 Mar 2010 20:26:00 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">class Base
{
    public:
        virtual ~Base()
        {
        }

        void readAttributes(Attributes* data)
        {
            // erledige Base-Aufgaben
            readAttributeImpl();
        }

    private:
        virtual void readAttributeImpl(Attributes* data) = 0;
};

class Derived : public Base
{
    private:
        virtual void readAttributeImpl(Attributes* data)
        {
            // erledige Derived-Aufgaben
        }
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1862980</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1862980</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Mon, 01 Mar 2010 20:26:00 GMT</pubDate></item><item><title><![CDATA[Reply to Vererbung Funktionalität erweitern on Mon, 01 Mar 2010 20:28:29 GMT]]></title><description><![CDATA[<p>Mir ist keine andere Lösung bekannt.. Du musst den Methodenaufruf in jedem Fall an irgendeiner Stelle machen.</p>
<p>Bei 5 Hirarchie Ebenen und Aufrufen von Funktionen aus der Basis Klasse würde ich mir aber an deiner Stelle mal überlegen ob das Design Konzept stimmt.</p>
<p>Außerdem: wenn du die Methode aus der Basis Klasse jedes mal aufrufst, liegt meiner Meinung nach der Design Fehler schon darin das eine Methode die dauernd benutzt wird trotzdem abgeleitet wird. Ich würde die Methode dann eher protected machen in der Basis Klasse und eine Extra Methode virtual...=0; zusätzlich einbauen.</p>
<p>#edit: Ok, Nexus war schneller und hat sogar eine Lösung. Über dein Design solltest du meiner Meinung nach trotzdem mal nachdenken, 5 Ebenen sind meiner Meinung nach sehr viel.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1862981</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1862981</guid><dc:creator><![CDATA[blub* 0]]></dc:creator><pubDate>Mon, 01 Mar 2010 20:28:29 GMT</pubDate></item><item><title><![CDATA[Reply to Vererbung Funktionalität erweitern on Mon, 01 Mar 2010 20:26:56 GMT]]></title><description><![CDATA[<p>Das ist eine der Gründe, warum man virtuelle Funktktionen nicht als Schnittstelle anbieten sollte. Schau dir mal das <a href="http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface" rel="nofollow">NVI Idiom</a> an.</p>
<p>Du kommst so aber nicht um Mehrfache Funktionen nicht rum. Allerdings ist dann die Basisklasse für das Aufrufen verantwortlich und nicht die abgeleitete.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1862982</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1862982</guid><dc:creator><![CDATA[drakon]]></dc:creator><pubDate>Mon, 01 Mar 2010 20:26:56 GMT</pubDate></item><item><title><![CDATA[Reply to Vererbung Funktionalität erweitern on Tue, 02 Mar 2010 15:36:57 GMT]]></title><description><![CDATA[<p>Danke erstmal für die Antworten.</p>
<p>Allerdings haben die mich nicht so sehr weitergebracht, auch wenn ich mir NVI mal angeschaut habe.</p>
<p>Vielleicht habe ich das Beispiel zu sehr reduziert...</p>
<p>Für alle Objekte im Programm, deren Daten aus einer Datei eingelesen bzw. in eine Datei geschrieben werden sollen, gibt es eine abstrakte Basisklasse:</p>
<pre><code class="language-cpp">class IAttributesObject{
 public:
  virtual void readAttributes(const Attributes* data) = 0;
  virtual void writeAttributes(Attributes* data) const = 0;
}
</code></pre>
<p>Dann gibt es z.B. die Objekte einer Szene, die z.B. alle durch Position, Rotation u. Skalierung. Davon abgeleitet gibt es z.B. Klassen für Lichtquellen, Darstellbare Objekte, .... Davon abgeleitet gibt es dann erst die konkrete Implementierung. Auf diese Art und Weise kommt dann schon eine recht große Hierarchietiefe zustande, die aber wohl schwierig vermeidbar ist. (ich bin mir jetzt nicht ganz sicher ob es auch irgnedwo 5 ebenen sind, aber die meisten implementierungen sind auf der 4. Ebene)</p>
<p>Die Methode von Nexus scheint mir daher auch ideal, da in jeder Ebene weitere Daten hinzukommen, sodass ich diese Funktionen in jeder Ebene erneuern müsste, was dann auch kein Vorteil wäre.</p>
<p>Ich hätte halt gedacht dass man sowas vielleicht mit templates lösen könnte. Zumindest theoretisch könnte man es ja folgendermaßen machen:</p>
<pre><code class="language-cpp">class IAttributesObject{
 public:
  virtual void readAttributes(const Attributes* data) = 0;
  virtual void writeAttributes(Attributes* data) const = 0;
 protected:
  virtual void doReadAttributes(const Attributes* data) = 0;
  virtual void doWriteAttributes(Attributes* data) const = 0;
}
</code></pre>
<p>Dann würde in jeder abgeleiteten Klasse die readAttributes Funktion so aussehen:</p>
<pre><code class="language-cpp">Derived::readAttributes(const Attributes* data){
 Base::readAttributes(const Attributes* data);
 doReadAttributes();
}
</code></pre>
<p>, d.h. der Quelltext würde in jeder abgeleiteten Klasse gleich aussehen (ein entsprechendes typedef für Base vorrausgesetzt).<br />
Kann man sowas mit templates irgendwie realisieren (mit Makros ginge es sicherlich, aber templates wären deutlich schöner).</p>
<p>Eine Variante mit Templates, die ich ausprobiert habe, die auch funktioniert, basiert darauf, dass ich eine rekursive Templatefunktion habe, die für IAttributesObjekt partiell implementiert ist und für alle anderen Typen die eine doReadAttributes Funktion sowie sich selbst mit der Basisklasse als Templateparameter aufruft.<br />
Dieser Ansatz hat jedoch einige Nachteile.</p>
<ul>
<li>Zum Einen muss der Typ, bei dem die rekursion begonnen wird, explizit als templateparameter angegeben werden.</li>
<li>Außerdem müssen die do... Funtkionen dann public oder die templatefunktion in jeder klasse als friend deklariert werden, was ich nicht so toll finde.</li>
</ul>
<p>Ich hoffe, damit konnte ich etwas klarer stellen, was ich brauche.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1863372</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1863372</guid><dc:creator><![CDATA[ngc92]]></dc:creator><pubDate>Tue, 02 Mar 2010 15:36:57 GMT</pubDate></item><item><title><![CDATA[Reply to Vererbung Funktionalität erweitern on Tue, 02 Mar 2010 21:02:28 GMT]]></title><description><![CDATA[<blockquote>
<p>Die Methode von Nexus scheint mir daher auch ideal, da in jeder Ebene weitere Daten hinzukommen, sodass ich diese Funktionen in jeder Ebene erneuern müsste, was dann auch kein Vorteil wäre.</p>
</blockquote>
<p>Das ist genau das, was du mit dem NVI Idiom bekommst. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Finde ich auch am saubersten. Und da musst du keine Angst mehr haben, dass etwas vergessen geht, weil du das als Programmierer der Basisklasse in der Hand hast und du vergisst das da ja nicht. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1863522</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1863522</guid><dc:creator><![CDATA[drakon]]></dc:creator><pubDate>Tue, 02 Mar 2010 21:02:28 GMT</pubDate></item><item><title><![CDATA[Reply to Vererbung Funktionalität erweitern on Wed, 03 Mar 2010 10:14:21 GMT]]></title><description><![CDATA[<p>hmm, eig. meinte ich nicht ideal, weil es eben viel aufwand bedeuten würde, falls es irgendwie eine Lösung mit templates geben würde, wäre mir das schon lieber...</p>
<p>für eine Hierarchieebene finde ich diese Lösung ganz gut, aber wenn es tiefer geht artet dass dann wohl doch ein bisschen aus</p>
<p>ich hätte dann ja</p>
<pre><code class="language-cpp">class Base{
 public:
  void readAttributes(const Attributes* att){
   // ... Basisklassenaufgaben
   readAttributesImpl(att);
  }
 protected:
  virtual void readAttributesImpl(const Attributes* att) = 0;
};
</code></pre>
<p>in der abgeleiteten Klasse htte ich dann</p>
<pre><code class="language-cpp">class Derived1: public Base{
 protected:
  virtual void readAttributesImpl(const Attributes* att){
   // Aufgaben von Derived1
   readAttributesImplD1(att);
  }
  virtual void readAttributesImplD1(const Attributes*) = 0;
}
</code></pre>
<p>und dann eben in jeder Ebene so weiter...</p>
<p>es garantiert auf jden Fall, dass man die Funktionsaufrufe nicht vergisst, da die ja schon in der Basisklasse stehen, aber man bekommt eben jede Ebene wieder ne neue Funktion dazu...</p>
<p>Eben gerade deswegen würde was templateartiges mir gefallen, zu meinem Ansatz habe ich ja im letzen Post was geschrieben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1863676</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1863676</guid><dc:creator><![CDATA[ngc92]]></dc:creator><pubDate>Wed, 03 Mar 2010 10:14:21 GMT</pubDate></item><item><title><![CDATA[Reply to Vererbung Funktionalität erweitern on Wed, 03 Mar 2010 21:57:21 GMT]]></title><description><![CDATA[<p>Hmm. Ich denke nicht, dass du da was mit templates einsparen könntest. Du willst ja auf jeder Ebene die Möglichkeit haben den Code zu ergänzen. Und templates ersetzen virtuelle Funktionen auch nicht, wenn du sie wirklich brauchst. Von dem her finde ich die Lösung so gar nicht schlecht.</p>
<p>btw:<br />
Du kannst die zu überschreibenden Funktionen sogar private machen. Überschreiben kannst du sie trotzdem. Und aufrufen muss sie ja grundsätzlich nur die Basisklasse.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1864014</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1864014</guid><dc:creator><![CDATA[drakon]]></dc:creator><pubDate>Wed, 03 Mar 2010 21:57:21 GMT</pubDate></item><item><title><![CDATA[Reply to Vererbung Funktionalität erweitern on Thu, 04 Mar 2010 18:35:23 GMT]]></title><description><![CDATA[<p>OK, wahrscheinlich ist das doch die beste Lösung. Aber dann habe ich nochmal ne Frage:</p>
<p>Wenn ich eine Hierarchietiefe von drei hätte, wäre dass dann ja folgendermaßen:</p>
<pre><code class="language-cpp">class Base{
 public:
  void f(){
   // gemeinsamer code
   //...

   // code, den die abgeleiteten Klassen zur Verfügung stellen
   f_impl();
  }
 private:
  virtual void f_impl() = 0;
};

class Der1: public Base{
 private:
  virtual void f_impl(){
   // gemeinsamer code für alle Der1 Objekte
   // ...

   // code, den die abgeleiteten Klassen zur Verfügung stellen
   f_impl_2();

   virtual void f_impl_2() = 0;
  }
};

class Der2: public Der1{
 private:
  virtual void f_impl_2(){
   // code für f_impl_2()
  }
}
</code></pre>
<p>Das Problem bei der ganzen Sache ist jetzt, dass Der2 zwar gezwungen ist, f_impl_2 zu definieren, jedoch nicht daran gehindert wird, die Implementierung von f_impl zu ändern.</p>
<p>Gibt es eine Möglichkeit, abzusichern, dass eine Funktion nur in der Nächsttieferen Ableitungsebene geändert werden kann, bzw. dass sie nicht mehr geändert werden kann?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1864442</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1864442</guid><dc:creator><![CDATA[ngc92]]></dc:creator><pubDate>Thu, 04 Mar 2010 18:35:23 GMT</pubDate></item><item><title><![CDATA[Reply to Vererbung Funktionalität erweitern on Thu, 04 Mar 2010 19:26:35 GMT]]></title><description><![CDATA[<p>ngc92 schrieb:</p>
<blockquote>
<p>Gibt es eine Möglichkeit, abzusichern, dass eine Funktion nur in der Nächsttieferen Ableitungsebene geändert werden kann, bzw. dass sie nicht mehr geändert werden kann?</p>
</blockquote>
<p>Nein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1864468</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1864468</guid><dc:creator><![CDATA[drakon]]></dc:creator><pubDate>Thu, 04 Mar 2010 19:26:35 GMT</pubDate></item></channel></rss>