<?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 Typumwandlung &amp;amp; virtuelle Funktionen]]></title><description><![CDATA[<p>Huhu,</p>
<p>bin gerade (mal wieder) am C++ lernen für die kommende Klausur am Donnerstag. Es werden wenige Aufgaben zum Selberprogrammieren drankommen, dafür sehr viel Verständniskram - und das auf einem relativ hohen Level.</p>
<p>Und genau bei Letzterem hakt es gerade. Folgende Aufgabe wurde in einer Klausur der letzten Jahren gestellt:</p>
<pre><code class="language-cpp">class Koerper {
public:
   int el;                  // Teil c)
   Koerper() { el = 5; cout &lt;&lt; el; }
   void f(int i) {i = i + el; el = i; cout &lt;&lt; getel(); }
   int getel() {return el;}                              // Z6
}
class Kugel : public Koerper {
public:
   int getel() {return (el-4);}
};
</code></pre>
<p>Das zugehörige Hauptprogramm:</p>
<pre><code class="language-cpp">int main() {
  Koerper k1;            // 5 / 5
  Koerper* k2;           // 
  Kugel k3;              // 5 / 5
  cout &lt;&lt; k3.getel();    // 1 / 1
  k1 = k3;               //
  cout &lt;&lt; k1.getel();    // 5 / 5
  k2 = &amp;k3;              // 
  cout &lt;&lt; k2-&gt;getel();   // 5 / 1
  k2-&gt;f(0);              // 5 / 1
}
</code></pre>
<p><em>Tragen Sie die Ausgaben zeilengenau in die vorbereiteten Tabellen ein. In die linke Tabelle kommen die Ausgaben unter Verwendung der Originalklassen und in die rechte Tabelle die Ausgaben, wenn die Funktion getel in Zeile 6 virtuell wäre.</em></p>
<p>So, ich hoffe, ich hab's einigermaßen nachvollziehbar hingeschrieben. Die Kommentare im Hauptprogramm sind die Lösungen von Teil a) / b) bzw. getel nicht virtuell / getel virtuell.</p>
<p>Bisher dachte ich, dass die Faustregel für virtuelle Funktionen in etwa diese ist: &quot;Gibt es in Basisklasse und abgeleiteter Klasse eine Funktion gleichen Namens mit gleicher Signatur, so wird stets die Funktion der Basisklasse aufgerufen, auch wenn man eigentlich auf die der abgeleiteten zugreifen will. Um Letzteres wirklich zu erreichen, muss man die Funktion virtual deklarieren.&quot;</p>
<p>Das scheint nun so nicht zu stimmen, auch wenn dies die einzige Aufgabe dieser Art war, bei der die Faustregel nicht anwendbar war. Und jetzt endlich mal zu den eigentlichen Verständnisfragen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /> :</p>
<p>a) Die Zeile k1 = k3 im Hauptprogramm verstehe ich nicht vollständig. Da wird aus einem Körper mittels impliziter Typumwandlung eine Kugel gemacht, so weit, so gut. Aber was passiert da genau? Welches getel habe ich nachher in k1 drinstehen (überschrieben ja/nein?)</p>
<p>b) Welchen Unterschied im Bezug auf virtuelle Funktionen macht es genau, ob ich nun mit (k2-&gt;getel) oder ohne (k3.getel) arbeite?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/260079/verständnisfrage-typumwandlung-amp-virtuelle-funktionen</link><generator>RSS for Node</generator><lastBuildDate>Tue, 08 Sep 2026 14:28:27 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/260079.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 31 Jan 2010 18:45:09 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Verständnisfrage Typumwandlung &amp;amp; virtuelle Funktionen on Sun, 31 Jan 2010 18:45:09 GMT]]></title><description><![CDATA[<p>Huhu,</p>
<p>bin gerade (mal wieder) am C++ lernen für die kommende Klausur am Donnerstag. Es werden wenige Aufgaben zum Selberprogrammieren drankommen, dafür sehr viel Verständniskram - und das auf einem relativ hohen Level.</p>
<p>Und genau bei Letzterem hakt es gerade. Folgende Aufgabe wurde in einer Klausur der letzten Jahren gestellt:</p>
<pre><code class="language-cpp">class Koerper {
public:
   int el;                  // Teil c)
   Koerper() { el = 5; cout &lt;&lt; el; }
   void f(int i) {i = i + el; el = i; cout &lt;&lt; getel(); }
   int getel() {return el;}                              // Z6
}
class Kugel : public Koerper {
public:
   int getel() {return (el-4);}
};
</code></pre>
<p>Das zugehörige Hauptprogramm:</p>
<pre><code class="language-cpp">int main() {
  Koerper k1;            // 5 / 5
  Koerper* k2;           // 
  Kugel k3;              // 5 / 5
  cout &lt;&lt; k3.getel();    // 1 / 1
  k1 = k3;               //
  cout &lt;&lt; k1.getel();    // 5 / 5
  k2 = &amp;k3;              // 
  cout &lt;&lt; k2-&gt;getel();   // 5 / 1
  k2-&gt;f(0);              // 5 / 1
}
</code></pre>
<p><em>Tragen Sie die Ausgaben zeilengenau in die vorbereiteten Tabellen ein. In die linke Tabelle kommen die Ausgaben unter Verwendung der Originalklassen und in die rechte Tabelle die Ausgaben, wenn die Funktion getel in Zeile 6 virtuell wäre.</em></p>
<p>So, ich hoffe, ich hab's einigermaßen nachvollziehbar hingeschrieben. Die Kommentare im Hauptprogramm sind die Lösungen von Teil a) / b) bzw. getel nicht virtuell / getel virtuell.</p>
<p>Bisher dachte ich, dass die Faustregel für virtuelle Funktionen in etwa diese ist: &quot;Gibt es in Basisklasse und abgeleiteter Klasse eine Funktion gleichen Namens mit gleicher Signatur, so wird stets die Funktion der Basisklasse aufgerufen, auch wenn man eigentlich auf die der abgeleiteten zugreifen will. Um Letzteres wirklich zu erreichen, muss man die Funktion virtual deklarieren.&quot;</p>
<p>Das scheint nun so nicht zu stimmen, auch wenn dies die einzige Aufgabe dieser Art war, bei der die Faustregel nicht anwendbar war. Und jetzt endlich mal zu den eigentlichen Verständnisfragen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /> :</p>
<p>a) Die Zeile k1 = k3 im Hauptprogramm verstehe ich nicht vollständig. Da wird aus einem Körper mittels impliziter Typumwandlung eine Kugel gemacht, so weit, so gut. Aber was passiert da genau? Welches getel habe ich nachher in k1 drinstehen (überschrieben ja/nein?)</p>
<p>b) Welchen Unterschied im Bezug auf virtuelle Funktionen macht es genau, ob ich nun mit (k2-&gt;getel) oder ohne (k3.getel) arbeite?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1848199</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1848199</guid><dc:creator><![CDATA[Luno]]></dc:creator><pubDate>Sun, 31 Jan 2010 18:45:09 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage Typumwandlung &amp;amp; virtuelle Funktionen on Sun, 31 Jan 2010 19:45:22 GMT]]></title><description><![CDATA[<p>a) bei der Zuweisung &quot;k1 = k3&quot; machst du nicht plötzlich aus dem Körper (k1) eine Kugel. Jede Kugel ist auch ein Körper, hat damit einen Anteil Körper intus. Bei der Zuweisung wird genau dieser Anteil kopiert! Deshalb ist jetzt aber k1 nicht gleich eine kugel (wie auch)</p>
<p>b) k1 und k3 sind Objekte im SPeicher, keine Referenzen/Pointer. wenn du eine Funktion direkt auf k1 oder k3 aufrufst (k1.getel()) wird auch immer Koerper::getel() (k1) bzw. Kugel::getel() (k3) aufgerufen, jenachdem als was k1/k3 deklariert wurde! Egal ob getel jetzt virtual oder nicht deklariert ist.<br />
k2 hingegen ist ein Pointer. hier wird beim Dereferenzieren geschaut ob ne virtuelle Tabelle (oder was auch immer dein Compiler erstellt, wenn &quot;virtual&quot; auftaucht) existiert. existiert diese, wird der genaue Typ des referenzierten Objekts ermittelt. In deinem Beispiel in Zeile 8 ist das eine Kugel. Somit wird - falls virtual - Kugel::getel() aufgerufen. Falls getel nicht virtual ist, ist es Koerper::getel() - k2 ist deklariert als &quot;pointer auf Koerper&quot;.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1848235</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1848235</guid><dc:creator><![CDATA[l&#x27;abra d&#x27;or]]></dc:creator><pubDate>Sun, 31 Jan 2010 19:45:22 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage Typumwandlung &amp;amp; virtuelle Funktionen on Sun, 31 Jan 2010 19:56:24 GMT]]></title><description><![CDATA[<p>zu deiner Frage a)<br />
In der Zeile k1 = k3 wird alles Kopiert, d.h. dein Abgeleitetes Objekt(Kugel) wird zur Basisklasse(Koerper). Das nennt sich 'slicing', weil Informationen(von der Abgeleiteten Klasse) verloren gehen(&quot;wegegeschnitten&quot; werden). Dadurch hast du in k1 das getel() von Koerper.</p>
<p>In der nächsten Zeile k2 = &amp;k3 wird lediglich die Adresse mit hilfe des Adressoperatos '&amp;' zugewiesen, d.h. das Abgeleitete Objekt ist immernoch die Kugel und hier kommt das virtual in Spiel.</p>
<p>Der Compiler merkt sich das k2 ein Pointer vom Typ Koerper ist, aber er merkt sich auch, dass k3 vom Typ Kugel ist. Das virtual bewirkt, dass die Funktion der Abgeleiteten Klasse nun bevorzugt aufgerufen wird.</p>
<p>Neue Faustregel:<br />
&quot;Man verwendet virtual dann wenn man davon ausgeht, dass die erbenden Klassen die Funktion überschreiben und man sich wünscht das immer die richtige Funktion aufgerufen wird.&quot;</p>
<p>Die kommentare im folgenden sind als Sprechender Kompiler zu verstehen;)</p>
<pre><code class="language-cpp">Fall 1: cout &lt;&lt; k2-&gt;getel();  //k2 ist vom Typ Koerper*, also rufe ich die Funktion getel() von Koerper auf.

Fall 2: cout &lt;&lt; k2-&gt;getel();  //k2 ist vom Typ Koerper*, also rufe ich die Funktion getel() von Koerper auf, moment mal! 
//Da hat jemand virtual hingeschrieben, kann es sein, dass der inhalt auf den k2 zeigt doch nicht vom typ Koerper ist? 
//Ich schaue nach und stelle fest, der Inhalt von k2 ist in wahrheit eine Kugel, also rufe ich getel() von Kugel auf.
</code></pre>
<p>D.h. der Comiler &quot;schaut&quot;(der Compilter erstellt sich tatsächlich eine tabelle, weshalb viele virtuals calls Performanceeinbußen bringen) nach ob es wirklich die Basisklasse ist und nicht eine abgeleitete Klasse. Das kann er aber nur, wenn du mit Referenzen und Pointern arbeitest. Im Fall k1 = k3 wurde es einfach kopiert und ist daher nicht mehr nachvollziehbar, weil kein Verweis(Pointer) auf das original mehr existiert.</p>
<p>zu b)<br />
bei k2-&gt;getel() muss er das virtual berücksichtigen, denn das Original könnte nicht vom typ k2 sein.<br />
Bei k3.getel() ignoriert er das virtual, denn er hat bereits das Originalobjekt und dessen Typ.</p>
<p>Evtl. noch nützlich:</p>
<pre><code class="language-cpp">virtual int memberFunktion() = 0; //Das =0 macht die Funktion zu einer rein virtuellen Funktion
</code></pre>
<p>Diese rein virtuelle funktion MUSS von jeder Abgeleiteten Klasse überschrieben werden, sonst gibts einen Fehler.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1848238</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1848238</guid><dc:creator><![CDATA[JaykopX]]></dc:creator><pubDate>Sun, 31 Jan 2010 19:56:24 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage Typumwandlung &amp;amp; virtuelle Funktionen on Sun, 31 Jan 2010 20:08:03 GMT]]></title><description><![CDATA[<p>Danke schonmal für die Antworten, den Teil mit virtual hab ich jetzt (glaube ich) verstanden. Aber:</p>
<blockquote>
<p>In der Zeile k1 = k3 wird alles Kopiert, d.h. dein Abgeleitetes Objekt(Kugel) wird zur Basisklasse(Koerper).</p>
</blockquote>
<p>Ist es nicht genau andersherum? (Oder: Es wird doch k1 etwas zugewiesen, warum verändert sich dann k3?)</p>
<blockquote>
<p>Jede Kugel ist auch ein Körper, hat damit einen Anteil Körper intus. Bei der Zuweisung wird genau dieser Anteil kopiert! Deshalb ist jetzt aber k1 nicht gleich eine kugel (wie auch)</p>
</blockquote>
<p>Also bekommt k1 hier Daten kopiert, die er sowieso schon besitzt <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /> ?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1848251</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1848251</guid><dc:creator><![CDATA[Luno]]></dc:creator><pubDate>Sun, 31 Jan 2010 20:08:03 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage Typumwandlung &amp;amp; virtuelle Funktionen on Sun, 31 Jan 2010 20:13:39 GMT]]></title><description><![CDATA[<p>Luno schrieb:</p>
<blockquote>
<blockquote>
<p>In der Zeile k1 = k3 wird alles Kopiert, d.h. dein Abgeleitetes Objekt(Kugel) wird zur Basisklasse(Koerper).</p>
</blockquote>
<p>Ist es nicht genau andersherum? (Oder: Es wird doch k1 etwas zugewiesen, warum verändert sich dann k3?)</p>
</blockquote>
<p>k3 ändert sich doch gar nicht, sondern k1! In deinem Beispiel ist das jetzt weniger wild, Kugel hat keine weiteren Data-Member. Angenommen es gäbe noch einen radius in Kugel.<br />
Bei der Zuweisung k1 = k3 könnte der ja nicht in k1 kopiert werden - es fehlt schlicht der Speicher!</p>
<blockquote>
<blockquote>
<p>Jede Kugel ist auch ein Körper, hat damit einen Anteil Körper intus. Bei der Zuweisung wird genau dieser Anteil kopiert! Deshalb ist jetzt aber k1 nicht gleich eine kugel (wie auch)</p>
</blockquote>
<p>Also bekommt k1 hier Daten kopiert, die er sowieso schon besitzt <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /> ?</p>
</blockquote>
<p>Nein, k1 bekommt Daten kopiert, die in k3 liegen.</p>
<p>Machs dir nicht so kompliziert! Überleg dir was hier passiert, dann verstehst du das vllt. auch besser was hier hier erzählen:</p>
<pre><code class="language-cpp">Kugel k1;
Kugel k2;
k2 = k1;
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1848253</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1848253</guid><dc:creator><![CDATA[l&#x27;abra d&#x27;or]]></dc:creator><pubDate>Sun, 31 Jan 2010 20:13:39 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage Typumwandlung &amp;amp; virtuelle Funktionen on Sun, 31 Jan 2010 20:24:32 GMT]]></title><description><![CDATA[<p>Okay, einen hab ich aber noch :</p>
<p>l'abra d'or schrieb:</p>
<blockquote>
<p>Nein, k1 bekommt Daten kopiert, die in k3 liegen.</p>
</blockquote>
<p>JaykopX schrieb:</p>
<blockquote>
<p>Dadurch hast du in k1 das getel() von Koerper.</p>
</blockquote>
<p>Wenn die Daten von k3 in k1 kopiert wurden - warum bleibt das ursprüngliche getel() bestehen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1848257</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1848257</guid><dc:creator><![CDATA[Luno]]></dc:creator><pubDate>Sun, 31 Jan 2010 20:24:32 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage Typumwandlung &amp;amp; virtuelle Funktionen on Sun, 31 Jan 2010 20:30:59 GMT]]></title><description><![CDATA[<p>Luno schrieb:</p>
<blockquote>
<p>Wenn die Daten von k3 in k1 kopiert wurden - warum bleibt das ursprüngliche getel() bestehen?</p>
</blockquote>
<p>Weil Membermethoden im Gegensatz zu Memberdaten nicht pro Objektinstanz gespeichert werden, sondern nur einmal im Speicher liegen. Der compiler sorgt dafür, dass ein Objekt immer die Methoden bekommt die die entsprechende Klasse implementiert - solange es nicht virtulle Funktionen sind!</p>
<pre><code class="language-cpp">Koerper k1;
k1.getel();   // k1 ist ein Koerper -&gt; Koerper::getel()
Kugel k2;
k1 = k2;      // kopiere Koerper-Basisanteil von Kugel k2 in Koerper k1
k1.getel();   // k1 ist immer noch ein Koerper -&gt; Koerper::getel()
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1848260</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1848260</guid><dc:creator><![CDATA[l&#x27;abra d&#x27;or]]></dc:creator><pubDate>Sun, 31 Jan 2010 20:30:59 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisfrage Typumwandlung &amp;amp; virtuelle Funktionen on Sun, 31 Jan 2010 20:34:51 GMT]]></title><description><![CDATA[<p>Ok, ich verstehe dein Problem. Die formulierung war unglücklich von mir.<br />
Funktionen kann man nicht kopieren in dem sinne, sondern nur die Variabeln.<br />
D.h. das el wird einfach kopiert.</p>
<p>Und k1 ist vom Typ Koerper, daher kann k1 auch nichts anderes aufrufen als funktionen von sich selber, es ist kein Pointer.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1848264</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1848264</guid><dc:creator><![CDATA[JaykopX]]></dc:creator><pubDate>Sun, 31 Jan 2010 20:34:51 GMT</pubDate></item></channel></rss>