<?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[Verständnisfrage zu abstrakter Klasse]]></title><description><![CDATA[<p>Hi,</p>
<p>wenn ich eine abstrakte Klasse habe, z.B. Fahrzeug und leite dann davon mehrere Klassen ab, z.B. Auto und Fahrrad, dann ist ja der Sinn der abstrakten Klasse dass über virtual gleichnamige Methoden in den Ableitungen überschrieben und angepasst werden.</p>
<p>Was ist aber mit spezial Methoden, z.B. getHorsePower(), was ja in der Klasse Fahrrad nichts zu suchen hat. Gibt es außer dynamic_cast von Zeiger Basis auf Zeiger Ableitung einen anderen Weg ? Ich habe in einem Buch gelesen dass es ein Design-Fehler wäre wenn man downcastet, aber wie man es anders machen soll stand dann nicht mehr in dem Buch.</p>
<p>Bei Ableitungen von einer abstrakten Basisklasse gibt es doch immer wieder notwendige Spezial-Methoden für die entsprechende Unterklasse, die mit einer anderen Ableitung nichts zu tun haben. Und solche Sachen als virtual in die Basisklasse packen macht die ja auch irgengwann unübersichtlich, oder ?</p>
<p>Gibt es da nur downcasting oder alles als virtual in die Basisklasse ? Wo ist denn da ein Design-Fehler wenn man downcasting nimmt ?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/244715/verständnisfrage-zu-abstrakter-klasse</link><generator>RSS for Node</generator><lastBuildDate>Sat, 19 Sep 2026 04:53:05 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/244715.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 04 Jul 2009 16:53:00 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sat, 04 Jul 2009 16:53:00 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>wenn ich eine abstrakte Klasse habe, z.B. Fahrzeug und leite dann davon mehrere Klassen ab, z.B. Auto und Fahrrad, dann ist ja der Sinn der abstrakten Klasse dass über virtual gleichnamige Methoden in den Ableitungen überschrieben und angepasst werden.</p>
<p>Was ist aber mit spezial Methoden, z.B. getHorsePower(), was ja in der Klasse Fahrrad nichts zu suchen hat. Gibt es außer dynamic_cast von Zeiger Basis auf Zeiger Ableitung einen anderen Weg ? Ich habe in einem Buch gelesen dass es ein Design-Fehler wäre wenn man downcastet, aber wie man es anders machen soll stand dann nicht mehr in dem Buch.</p>
<p>Bei Ableitungen von einer abstrakten Basisklasse gibt es doch immer wieder notwendige Spezial-Methoden für die entsprechende Unterklasse, die mit einer anderen Ableitung nichts zu tun haben. Und solche Sachen als virtual in die Basisklasse packen macht die ja auch irgengwann unübersichtlich, oder ?</p>
<p>Gibt es da nur downcasting oder alles als virtual in die Basisklasse ? Wo ist denn da ein Design-Fehler wenn man downcasting nimmt ?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737088</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737088</guid><dc:creator><![CDATA[Trial]]></dc:creator><pubDate>Sat, 04 Jul 2009 16:53:00 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sat, 04 Jul 2009 17:00:32 GMT]]></title><description><![CDATA[<p>Dass <code>dynamic_cast</code> mit dem Designfehler verbunden ist, stimmt in vielen (aber nicht allen) Fällen. Der Sinn von virtuellen Funktionen ist es ja gerade, eine einheitliche Schnittstelle zu bilden für Funktionalität, die die Basisklasse bereitstellt, aber die von jeder abgeleiteten Klasse anders implementiert werden. In deinem Fall willst du von einem Fahrzeug die Pferdestärken wissen, was nicht sinnvoll ist. Auch der Cast ist nicht unbedingt die Lösung.</p>
<p>Dieses Casten braucht man in einem gewissen Kontext, und solche Probleme entstehen oft durch zu wenig oder falsche Abstraktion. Musst du denn Autos, Velos und Boote gemeinsam ansprechen <strong>und</strong> dabei die PS wissen? Reicht es nicht, wenn du direkt Autos ansprichst?</p>
<p>Das tönt jetzt vielleicht alles etwas allgemein, aber du hast auch allgemeine Fragen gestellt. Wenn du einen konkreten Anwendungsfall beschreibst, können wir auch genauer darauf eingehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737094</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737094</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 04 Jul 2009 17:00:32 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sat, 04 Jul 2009 17:09:39 GMT]]></title><description><![CDATA[<p>Der Sinn einer Basisklasse ist es keineswegs, das komplette Interface aller abgeleiteten Klassen abzubilden. Deshalb kommen in eine abstrakte Basisklasse auch nur jene Elemente rein, die für alle möglichen abgeleiteten Klassen existieren und sinnvoll sind. Speziellere Elemente brauchst du ja auch gar nicht in der Basisklasse, wenn sie nicht für alle abgeleiteten Klassen einen Sinn ergeben:</p>
<pre><code class="language-cpp">struct Fahrzeug
{
    virtual int getHP() const = 0;    // &lt;- hat hier nichts zu suchen
};

struct Auto : public Fahrzeug {};

struct Fahrrad : public Fahrzeug {};
</code></pre>
<p>Was soll Fahrrad::getHP() zurückgeben? Die PS-Zahl macht nur für motorisierte Fahrzeuge einen Sinn. Deshalb soll man diese Funktion auch erst frühestens in einer Basisklasse MotorFahrzeug deklarieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737096</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737096</guid><dc:creator><![CDATA[Michael E.]]></dc:creator><pubDate>Sat, 04 Jul 2009 17:09:39 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sat, 04 Jul 2009 18:03:40 GMT]]></title><description><![CDATA[<p>Genau hier liegt mein Verständnisproblem:</p>
<pre><code class="language-cpp">class Fahrzeug 
{ 
    virtual int getHP() const = 0;    // &lt;- hat hier nichts zu suchen 
}; 

class Auto : public Fahrzeug
{
 int getHP();   // hier macht die Methode Sinn
}; 

class Fahrrad : public Fahrzeug {};  // hier nicht, deshalb auch nicht in Fahrzeug
</code></pre>
<p>Aber wenn ich jetzt eine Instanz Auto erzeugt habe, dann kann ich nur mittels dynamic_cast von Fahrzeug --&gt; Auto auf getHP() zugreifen.<br />
Ist das dann ein Designfehler ?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737120</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737120</guid><dc:creator><![CDATA[Trial]]></dc:creator><pubDate>Sat, 04 Jul 2009 18:03:40 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sat, 04 Jul 2009 18:12:30 GMT]]></title><description><![CDATA[<p>Wie Michael E. bereits gesagt hat: Füg doch einfach eine Klasse MotorisiertesFahrzeug in die Hierarchie ein und verschieb die Methode in diese Klasse.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737127</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737127</guid><dc:creator><![CDATA[this-*gt*that]]></dc:creator><pubDate>Sat, 04 Jul 2009 18:12:30 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sat, 04 Jul 2009 18:20:13 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">Auto auto_;
std::cout &lt;&lt; auto_.getPS();
</code></pre>
<p>Ist absolut kein Problem. Schwierig wird es nur, wenn du eine Referenz/Zeiger auf ein Fahrzeug hast. Du weißt dann nicht, ob es überhaupt einen Antrieb hat, den man in PS messen kann. Folglich ist eine Abfrage fahrzeug-&gt;getPS() unmöglich.</p>
<p>Schauen wir uns einmal folgenden Code an:</p>
<pre><code class="language-cpp">void GibPsAus(Fahrzeug const&amp; fahrzeug)
{
    std::cout &lt;&lt; dynamic_cast&lt;Auto const&amp;&gt;(fahrzeug)-&gt;getPS();
}
</code></pre>
<p>Die Methode funktioniert nur, wenn der Parameter <code>fahrzeug</code> ein Auto ist. Also hätte man auch gleich als Parameter ein Auto angeben können. Verwendet man dynamic_cast, weil man weiß, dass eine Basisklassenreferenz einen bestimmten abgeleiteten Typ hat, hätte man auch direkt auf diesem Typ arbeiten können. Das ist z.B. eine unnötige Verwendung von dynamic_cast.</p>
<p>Außerdem solltest du dynamic_cast nicht verwenden, um den Typen abzufragen. Dafür gibt es virtuelle Funktionen. Also statt:</p>
<pre><code class="language-cpp">if (fahrrad = dynamic_cast&lt;Fahrrad*&gt;(fahrzeug))
    fahrrad-&gt;trete_in_die_pedale();
else if (auto_ = dynamic_cast&lt;Auto*&gt;(fahrzeug))
    auto_-&gt;trete_das_gas_pedal();
</code></pre>
<p>Lieber eine abstrakte virtuelle Methode:</p>
<pre><code class="language-cpp">fahrzeug-&gt;beschleunige();
</code></pre>
<p>Gibt sicherlich noch mehr Negativ-Beispiele. Ich habe dynamic_cast noch nie gebraucht. Wäre deshalb wohl interessiert an einem Positiv-Beispiel, in dem man dynmaic_cast benötigt.</p>
<p>Gruß<br />
Don06</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737129</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737129</guid><dc:creator><![CDATA[Don06]]></dc:creator><pubDate>Sat, 04 Jul 2009 18:20:13 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sat, 04 Jul 2009 18:23:09 GMT]]></title><description><![CDATA[<p>Trial schrieb:</p>
<blockquote>
<p>Aber wenn ich jetzt eine Instanz Auto erzeugt habe, dann kann ich nur mittels dynamic_cast von Fahrzeug --&gt; Auto auf getHP() zugreifen.</p>
</blockquote>
<p>Nein, du brauchst den dynamic_cast nur, wenn du mit einem Basisklassenzeiger auf dieses Objekt zeigst. Das ist nur nötig, wenn du eine Sammlung von Fahrzeugen hast mit allen möglichen Fahrzeugtypen. Wenn du allerdings alle möglichen Fahrzeugtypen hast, macht eine Abfrage der PS-Zahl keinen Sinn.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737131</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737131</guid><dc:creator><![CDATA[Michael E.]]></dc:creator><pubDate>Sat, 04 Jul 2009 18:23:09 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sat, 04 Jul 2009 18:35:18 GMT]]></title><description><![CDATA[<p>Trial schrieb:</p>
<blockquote>
<p>Aber wenn ich jetzt eine Instanz Auto erzeugt habe, dann kann ich nur mittels dynamic_cast von Fahrzeug --&gt; Auto auf getHP() zugreifen.</p>
</blockquote>
<p>Eben, hast du einen konkreten Anwendungsfall, bei dem du das musst und nicht direkt über die <code>Auto</code> -Klasse zugreifen kannst? Deshalb fragte ich ja vorhin. Gut möglich, dass wir dir Alternativen zeigen können.</p>
<p>Don06 schrieb:</p>
<blockquote>
<p>Ich habe dynamic_cast noch nie gebraucht. Wäre deshalb wohl interessiert an einem Positiv-Beispiel, in dem man dynmaic_cast benötigt.</p>
</blockquote>
<p>Hier gabs mal so einen Thread: <a href="http://www.c-plusplus.net/forum/viewtopic-var-t-is-238923.html" rel="nofollow">http://www.c-plusplus.net/forum/viewtopic-var-t-is-238923.html</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737139</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737139</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sat, 04 Jul 2009 18:35:18 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sun, 05 Jul 2009 08:58:07 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>mein Beispiel bezieht sich hier auf das Erstellen von Testdateien für verschiedene Drucker. In der Basisklasse sind die Eigenschaften wie Größe, Auflösung, Datenformat, Farbe etc. und in der jeweiligen Ableitung werden noch spezielle Daten für den ausgewählten Drucker aufbereitet.<br />
Hier habe ich meinen Ablauf etwas zusammengefaßt:</p>
<pre><code class="language-cpp">// TestFile ist die Basisklasse
// SPrinterIJ, LPrinterES und andere sind die Ableitungen

TestFile *TF = 0;         // Deklaration und Initialisieren von TF (Basisklasse)

...

// Hier wird abhängig von PrinterType das entsprechende Objekt erzeugt
switch ( PrinterType )
	  {
	   case SPrinterIJ:
						 TF = new SPrinterIJ();
						 break;
	   case LPrinterES:
						 TF = new LPrinterES();
						 break;
...

            default:
						 break;
	  }

...

// Um die Funktion getJobParameter in der Ableitung SPrinterIJ anzusprechen muss ich den Zeiger casten
SPrinterIJ *ptrPrinter = 0;
ptrPrinter = dynamic_cast&lt;SPrinterIJ*&gt;(TF);
if ( ptrPrinter != 0 )
  {
   ptrPrinter-&gt;getJobParameter( sJobParam );
  }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1737344</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737344</guid><dc:creator><![CDATA[Trial]]></dc:creator><pubDate>Sun, 05 Jul 2009 08:58:07 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sun, 05 Jul 2009 09:46:22 GMT]]></title><description><![CDATA[<p>Also erstmal ist der Name der Basisklasse unglücklich. Denn ein Drucker ist kein File.</p>
<p>Jeder Drucker hat Parameter. Also kannst du die Funktion getJobParameters() in die Basisklasse AbstractPrinter stecken.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737363</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737363</guid><dc:creator><![CDATA[Michael E.]]></dc:creator><pubDate>Sun, 05 Jul 2009 09:46:22 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sun, 05 Jul 2009 10:22:45 GMT]]></title><description><![CDATA[<p>Michael E. schrieb:</p>
<blockquote>
<p>Also erstmal ist der Name der Basisklasse unglücklich. Denn ein Drucker ist kein File.</p>
</blockquote>
<p>Den Namen habe ich gewählt weil das Endprodukt eine Testdatei ist.</p>
<p>Michael E. schrieb:</p>
<blockquote>
<p>Jeder Drucker hat Parameter. Also kannst du die Funktion getJobParameters() in die Basisklasse AbstractPrinter stecken.</p>
</blockquote>
<p>Ja, das stimmt, aber in diesem Fall ist die Funktion für einen &quot;speziellen&quot; Job Header gedacht, der nur bei dem Model SPrinterIJ gebraucht wird. Alle anderen Druckerparameter werden über Methoden der Basisklasse definiert.<br />
Dann ist doch das downcasten in Ordnung, oder nicht ?!</p>
<p>Ich gebe ja zu mit der Namensvergabe komm ich auch oft ins grübeln <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f921.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--clown_face"
      title=":clown:"
      alt="🤡"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737382</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737382</guid><dc:creator><![CDATA[Trial]]></dc:creator><pubDate>Sun, 05 Jul 2009 10:22:45 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sun, 05 Jul 2009 10:53:38 GMT]]></title><description><![CDATA[<p>Trial schrieb:</p>
<blockquote>
<p>Michael E. schrieb:</p>
<blockquote>
<p>Also erstmal ist der Name der Basisklasse unglücklich. Denn ein Drucker ist kein File.</p>
</blockquote>
<p>Den Namen habe ich gewählt weil das Endprodukt eine Testdatei ist.</p>
</blockquote>
<p>Und diese Testdatei ist Basisklasse deiner Drucker? Ich denke, du siehst den Designfehler hier. Denn ich mache Benzin auch nicht zur Basisklasse einer Tankstelle.</p>
<blockquote>
<p>Ja, das stimmt, aber in diesem Fall ist die Funktion für einen &quot;speziellen&quot; Job Header gedacht, der nur bei dem Model SPrinterIJ gebraucht wird. Alle anderen Druckerparameter werden über Methoden der Basisklasse definiert.<br />
Dann ist doch das downcasten in Ordnung, oder nicht ?!</p>
</blockquote>
<p>Für die zusätzlichen Parameter brauchst du aber keine neue Funktion.</p>
<pre><code class="language-cpp">struct AbstractPrinter
{
	virtual void setParameters() = 0;

private:
	size_t breite_;
	size_t hoehe_;
};

struct NormalPrinter : public AbstractPrinter
{
	virtual void setParameters(size_t breite, size_t hoehe)
	{
		breite_ = breite;
		hoehe_ = hoehe;
	}
};

struct SuperSpecialPrinter : public AbstractPrinter
{
	virtual void setParameters(size_t breite, size_t hoehe, int specialParameter)
	{
		breite_ = breite;
		hoehe_ = hoehe;
		specialParameter_ = specialParameter;
	}

private:
	int specialParameter_;
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1737396</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737396</guid><dc:creator><![CDATA[Michael E.]]></dc:creator><pubDate>Sun, 05 Jul 2009 10:53:38 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage zu abstrakter Klasse on Sun, 05 Jul 2009 11:32:18 GMT]]></title><description><![CDATA[<p>Hallo Michael,</p>
<p>vielen Dank für dein Beispiel ! Jetzt ist mir das schon klarer geworden. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1737415</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1737415</guid><dc:creator><![CDATA[Trial]]></dc:creator><pubDate>Sun, 05 Jul 2009 11:32:18 GMT</pubDate></item></channel></rss>