<?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[[Erledigt] CRTP Frage]]></title><description><![CDATA[<p>Hallo Leute!<br />
Ich habe ein Problem mit CRTP. Ich habe mir, um zu stehen was passiert eine kleines Beispiel gebaut:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

template&lt; typename T &gt;
class Worker
{
public:
    void show( )
    {
		std::cout &lt;&lt; typeid( T ).name( ) &lt;&lt; std::endl;
		T* c = reinterpret_cast&lt; T* &gt;( this );
		if( c-&gt;alter &gt; 18 )
		{
			std::cout &lt;&lt; &quot;okay, &quot; &lt;&lt; c-&gt;name.data( ) &lt;&lt; &quot; kann arbeiten!&quot; &lt;&lt; std::endl;
		};
    }
};

class Lehrling : public Worker&lt; Lehrling &gt;
{
private:
public:
	std::string name;
	int alter;
    Lehrling( std::string n, int alt ) : name( n ), alter( alt )
    {
    }
};

int main( int arg, char* arvg[ ] )
{
    Lehrling l( &quot;frank&quot;, 19 );
l.show( );
    return 0;
}
</code></pre>
<p>Ich komme mit dieser Zeile nicht klar:</p>
<pre><code class="language-cpp">T* c = reinterpret_cast&lt; T* &gt;( this );
</code></pre>
<p>Hier wird doch ein Pointer, vom Typ Lehrling, auf meine Klasse Worker erstellt. Wie kann den dieser Pointer auf die Werte wie Alter etc. zugreifen, wenn er auf eine ganz andere Klasse zeigt. Ich habe das Projekt mal in Olly versucht zu debuggen. Dort wird vor dem call</p>
<pre><code class="language-cpp">l.show( );
</code></pre>
<p>die Adresse der Klasse Lehrling in eax geladen und und bei dem call verwendet um an den Namen und Alter zukommen. Deshalb: Warum muss der Cast so sein?<br />
Ich würde mich sehr über eine ausführliche Erklärung freuen.</p>
<p>MfG yihaaa</p>
<p>BTW: Ich benutze MSVS Express 2008, falls dies von Bedeutung sein könnte.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/303992/erledigt-crtp-frage</link><generator>RSS for Node</generator><lastBuildDate>Mon, 10 Aug 2026 03:54:15 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/303992.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 27 May 2012 13:41:12 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Mon, 28 May 2012 09:25:35 GMT]]></title><description><![CDATA[<p>Hallo Leute!<br />
Ich habe ein Problem mit CRTP. Ich habe mir, um zu stehen was passiert eine kleines Beispiel gebaut:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

template&lt; typename T &gt;
class Worker
{
public:
    void show( )
    {
		std::cout &lt;&lt; typeid( T ).name( ) &lt;&lt; std::endl;
		T* c = reinterpret_cast&lt; T* &gt;( this );
		if( c-&gt;alter &gt; 18 )
		{
			std::cout &lt;&lt; &quot;okay, &quot; &lt;&lt; c-&gt;name.data( ) &lt;&lt; &quot; kann arbeiten!&quot; &lt;&lt; std::endl;
		};
    }
};

class Lehrling : public Worker&lt; Lehrling &gt;
{
private:
public:
	std::string name;
	int alter;
    Lehrling( std::string n, int alt ) : name( n ), alter( alt )
    {
    }
};

int main( int arg, char* arvg[ ] )
{
    Lehrling l( &quot;frank&quot;, 19 );
l.show( );
    return 0;
}
</code></pre>
<p>Ich komme mit dieser Zeile nicht klar:</p>
<pre><code class="language-cpp">T* c = reinterpret_cast&lt; T* &gt;( this );
</code></pre>
<p>Hier wird doch ein Pointer, vom Typ Lehrling, auf meine Klasse Worker erstellt. Wie kann den dieser Pointer auf die Werte wie Alter etc. zugreifen, wenn er auf eine ganz andere Klasse zeigt. Ich habe das Projekt mal in Olly versucht zu debuggen. Dort wird vor dem call</p>
<pre><code class="language-cpp">l.show( );
</code></pre>
<p>die Adresse der Klasse Lehrling in eax geladen und und bei dem call verwendet um an den Namen und Alter zukommen. Deshalb: Warum muss der Cast so sein?<br />
Ich würde mich sehr über eine ausführliche Erklärung freuen.</p>
<p>MfG yihaaa</p>
<p>BTW: Ich benutze MSVS Express 2008, falls dies von Bedeutung sein könnte.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2216006</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216006</guid><dc:creator><![CDATA[yihaaa]]></dc:creator><pubDate>Mon, 28 May 2012 09:25:35 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Sun, 27 May 2012 14:28:46 GMT]]></title><description><![CDATA[<p>Klassen haben keine Adressen und du kannst auch keine Pointer auf Klassen haben. Du musst Klasse von Objekt trennen. Klasse ist die Plätzchenform, Objekt ist das Plätzchen.</p>
<p>Ein reinterpret_cast macht auch rein technisch gar nichts. Das kannst du nicht im Debugger nachvollziehen. Es sagt dem Compiler bloß, dass er die Schnauze halten soll, weil alles so stimmt, auch wenn er meint, es wäre falsch.</p>
<p>Außerdem ist hier der reinterpret_cast gar nicht notwendig, aufgrund der Verwandschaft zwischen Worker und Lehrling ist eigentlich ein static_cast angesagt. Der (hier) technisch auch nichts macht, sondern dem Compiler sagt, dass er den this-Zeiger als auf eine andere Klasse zeigend ansehen soll, im Gegensatz zu reinterpret_cast jedoch mit ein paar Prüfungen, ob das auch Sinn macht (du könntest hier z.B. keinen static_cast auf int* machen).</p>
<p>Zusammenfassend:<br />
In Zeile 34 erzeugst du ein Lehrling-Objekt l. Auf dem l rufst du Worker&lt;Lehrling&gt;::show auf. Das geht, weil Lehrling von Worker&lt;Lehrling&gt; public erbt, also ein Worker&lt;Lehrling&gt; <strong>ist</strong>, wie man diese Verwandschaft beschreibt. Der this-Zeiger in Worker&lt;Lehrling&gt; zeigt also nicht bloß auf ein Worker&lt;Lehrling&gt;-Objekt, sondern auf ein Worker&lt;Lehrling&gt;-Objekt, welches gleichzeitig ein Teil eines Lehrling-Objektes (nämlich von l) ist. Daher ist es möglich, den this-Zeiger auch als einen Zeiger auf ein Lehrling-Objekt aufzufassen und das funktioniert, weil er tatsächlich auf ein Lehrling-Objekt zeigt.</p>
<p>Beachte auch, wie ich oben immer Worker&lt;Lehrling&gt; als Name der Klasse genannt habe. Worker ist nämlich nur eine Vorlage (engl. template) für eine Klasse. Die Konstruktionszeichnung für eine Plätzchenform sozusagen. Erst Worker&lt;Lehrling&gt; ist eine konkrete Klasse und erst in l lebt (durch die Vererbung) eine konkrete Instanz (ein Plätzchen) von Worker&lt;Lehrling&gt;.</p>
<p>P.S.: Vielleicht ist die Analogie mit den Plätzchen nicht die beste. Wenn jemand ein bessere hat, bin ich interessiert, diese zu hören.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2216011</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216011</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Sun, 27 May 2012 14:28:46 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Sun, 27 May 2012 15:00:38 GMT]]></title><description><![CDATA[<p>Okay, erst mal danke SeppJ!<br />
So, damit ich das auch richtig verstanden habe:<br />
Mit Lehrling l( name, 19 ); erstelle ich eine neue Objekt von Lehrling und von Worker&lt; Lehrling &gt;, die beide den gleichen this-Zeiger haben. Man muss ihn eben immer nur auf das richtig Objekt casten, damit der Compiler weiß, von welcher Klasse er z.B. Variablen und Funktionen nehmen soll?</p>
<p>MfG yihaaa</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2216018</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216018</guid><dc:creator><![CDATA[yihaaa]]></dc:creator><pubDate>Sun, 27 May 2012 15:00:38 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Sun, 27 May 2012 16:18:47 GMT]]></title><description><![CDATA[<p>yihaaa schrieb:</p>
<blockquote>
<p>Man muss ihn eben immer nur auf das richtig Objekt casten, damit der Compiler weiß, von welcher Klasse er z.B. Variablen und Funktionen nehmen soll?</p>
</blockquote>
<p>Nicht immer, normalerweise passt ja der Typ. Hier (also beim CRTP) jedoch kann der Compiler in Zeile 11 nicht wissen, dass die Methode später mal von einem Lehrling-Objekt aufgerufen wird.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2216029</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216029</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Sun, 27 May 2012 16:18:47 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Sun, 27 May 2012 16:30:15 GMT]]></title><description><![CDATA[<p>Danke. Noch eine kleine Frage, wie könnte ich jetz verhindern, dass eine Objekt von Worker&lt; X &gt;, z.B. Worker&lt; Lehrling &gt; i; erstellt wird?</p>
<p>MfG yihaaa</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2216033</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216033</guid><dc:creator><![CDATA[yihaaa]]></dc:creator><pubDate>Sun, 27 May 2012 16:30:15 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Sun, 27 May 2012 16:38:14 GMT]]></title><description><![CDATA[<p>Du kannst den Konstruktor des Worker-Templates protected machen, dann können nur davon abgeleitete Klassen ein Objekt erstellen:</p>
<pre><code class="language-cpp">template&lt; typename T &gt;
class Worker
{
protected:
  Worker() {};
 // ...
};

int main()
{
  Worker&lt;Lehrling&gt; ll;  // Compilerfehler
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2216036</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216036</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Sun, 27 May 2012 16:38:14 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Sun, 27 May 2012 17:31:04 GMT]]></title><description><![CDATA[<p>SeppJ schrieb:</p>
<blockquote>
<p>Außerdem ist hier der reinterpret_cast gar nicht notwendig, aufgrund der Verwandschaft zwischen Worker und Lehrling ist eigentlich ein static_cast angesagt. Der (hier) technisch auch nichts macht, sondern dem Compiler sagt, dass er den this-Zeiger als auf eine andere Klasse zeigend ansehen soll, im Gegensatz zu reinterpret_cast jedoch mit ein paar Prüfungen, ob das auch Sinn macht (du könntest hier z.B. keinen static_cast auf int* machen).</p>
</blockquote>
<p>Der <code>reinterpret_cast</code> ist nicht nur nicht notwendig, er ist auch falsch.<br />
Gibt ja Mehrfachvererbung.</p>
<pre><code class="language-cpp">class Lehrling : public Irgendwas, public Worker&lt; Lehrling &gt;
{
};
</code></pre>
<p>Und schon haben wir ein Problem.</p>
<p>Daher bei CRTP immer nur <code>static_cast</code> !</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2216053</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216053</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sun, 27 May 2012 17:31:04 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Sun, 27 May 2012 18:05:29 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/13960">@hustbaer</a>: Könntest du vielleicht mal erklären warum das mit reinterpret_cast und den Mehrfachvererbungen falsch läuft? Ich kann mir das gerade nur schwer vorstellen. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>MfG yihaaa</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2216062</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216062</guid><dc:creator><![CDATA[yihaaa]]></dc:creator><pubDate>Sun, 27 May 2012 18:05:29 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Sun, 27 May 2012 18:25:48 GMT]]></title><description><![CDATA[<p>yihaaa schrieb:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/13960">@hustbaer</a>: Könntest du vielleicht mal erklären warum das mit reinterpret_cast und den Mehrfachvererbungen falsch läuft? Ich kann mir das gerade nur schwer vorstellen. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>MfG yihaaa</p>
</blockquote>
<p>Das hat etwas mit der Anordnung im Speicher zu tun. Bei Vererbung besteht tatsächlich ein Mutterobjekt in dem beerbten Objekt. Angenommen Derived erbt von Base, dann sieht Derived so aus:</p>
<pre><code>this  -&gt;     ----------------
             |  Base-Teil   |
             ----------------
             | Derived-Teil |
             ----------------
</code></pre>
<p>Das heißt, hier hat der Zeiger auf den Teil Derived::Base tatsächlich den gleichen Zahlenwert wie der Zeiger auf das ganze Objekt. Hier funktionieren sowohl static_cast als auch reinterpret_cast. Hat man aber Mehrfachvererbung, so können die verschiedenen Basisobjekte ja nicht an der gleichen Stelle liegen. Erbt Derived von Base1 und Base2 (in dieser Reihenfolge), dann sieht Derived so aus:</p>
<pre><code>this  -&gt;     ----------------
             |  Base1-Teil  |
             ----------------
             |  Base2-Teil  |
             ----------------
             | Derived-Teil |
             ----------------
</code></pre>
<p>Wenn man nun einen reinterpret_cast&lt;Base2*&gt; auf this macht, dann wird der Zahlenwert von this genommen und als Base2 interpretiert (nichts anderes macht reinterpret_cast). this zeigt hier aber auf ein Base1-Objekt und <s>man ist gefickt</s> das ist nicht so günstig. Bei einem static_cast hatte ich oben geschrieben, dass er &quot;hier&quot; nichts machen würde und das war oben auch noch richtig. Bei der Mehrfachvererbung macht er aber tatsächlich was. Der Compiler kennt schließlich den Aufbau von Derived und weiß, wo der Base2-Teil eines Derived-Objektes relativ zum this-Zeiger des Derived-Objektes steht. Und wenn man nun sagt, dass man den Base2-Teil haben möchte, dann kann er dies korrekt umrechnen.</p>
<p>(Eventuelles Padding zwischen den Objekten habe ich der Einfachheit wegen weggelassen. )</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2216070</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216070</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Sun, 27 May 2012 18:25:48 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Sun, 27 May 2012 19:21:40 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/28665">@yihaaa</a><br />
SeppJ hat ja schon erklärt warum es in der Praxis ein Problem geben kann.</p>
<p>Der <code>reinterpret_cast</code> ist aber genaugenommen nicht deswegen falsch, weil es in der Praxis ein Problem geben kann, sondern weil der Standard einfach nicht garantiert dass es funktionieren muss.</p>
<p>Bei <code>static_cast</code> dagegen ist es garantiert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2216095</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216095</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sun, 27 May 2012 19:21:40 GMT</pubDate></item><item><title><![CDATA[Reply to [Erledigt] CRTP Frage on Mon, 28 May 2012 09:24:51 GMT]]></title><description><![CDATA[<p>Wow, vielen dank euch beiden! Ich hatte mir das falsch vorgestellt, ich hatte nicht gewusst, dass wenn man eine Klasse mit Ableitungen erstellt, dass dann diese zu einer großen Klasse zusammen den selben this-Zeiger benutzen. Danke für die Erklärung! <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>
<p>MfG yihaaa</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2216233</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2216233</guid><dc:creator><![CDATA[yihaaa]]></dc:creator><pubDate>Mon, 28 May 2012 09:24:51 GMT</pubDate></item></channel></rss>