<?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[Deklaration und Definition in zwei unterschiedliche geerbte Klassen trennen.]]></title><description><![CDATA[<p>Guten Tag,<br />
obwohl ich hier neu bin, komme auch sogleich mit einem für mich großem Problem(Und ich hoffe auch ein wenig für euch, damit ich mich selbst schon mal als einen einigermaßen erfahrenen Programmierer einschätzen kann. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /> ).</p>
<p>Hier zu meinem Problem:<br />
Ich habe eine Template-Klasse Inter, welche ein Interface darstellt und eine Methode foo(UnknownType) deklariert. Des weiteren erbt diese Klasse wieder von einer anderen Spezialisierung seiner Klasse(Inter). Dadurch enthält diese Klasse später viele abstakte foo-Methoden, welche sich nur durch ihren Übergabeparametertyp unterscheiden. Als Templateargument übergibt man der Klasse eine Typliste.<br />
Da die Anzahl der Methoden erst zur Kompilierungszeit bekannt ist, muss ich auch die Implementierung variabel halten. Dies habe ich mit einer weiteren Klasse Defin versucht, welche fast genauso aufgebaut ist, wie die Klasse Inter, nur dass die Methode nicht abstrakt, sondern vollständig definiert ist.<br />
Diese beiden erstellten Klassen versuche ich nun in einer nächsten Klasse Merge zusammenzuführen, in dem sie von beiden Klassen erbt. Leider klappt dies scheinbar so nicht. Sobald ich nämlich versuche eine Instanz von Merge zu erzeugen, wird mir gesagt, dass die Klasse abstrakt sei.<br />
Als Test habe ich mal folgendes Konstrukt geschrieben, welches leider auch nicht funktioniert:</p>
<pre><code class="language-cpp">class Inter
{
public:
	virtual ~Inter() {}
	virtual void foo() = 0;
};

class Defen
{
public:
	virtual ~Defen() {}
	virtual void foo() { cout &lt;&lt; &quot;Defen&quot;; }
};

class Merged: public Defen, public Inter
{
};
</code></pre>
<p>Daher ist nun meine Frage, ob es da eine Möglichkeit gibt, dies auf eine andere Weise zu implementieren oder ob ich einfach nur irgendwo einen Fehler gemacht habe.<br />
Der Grund, warum ich das alles eigentlich mache ist, weil man in C++ keine Template-Methoden virtuell machen kann, was wohl auch seinen Grund hat ...</p>
<p>Gruß, Mickeyman.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/259086/deklaration-und-definition-in-zwei-unterschiedliche-geerbte-klassen-trennen</link><generator>RSS for Node</generator><lastBuildDate>Tue, 08 Sep 2026 21:26:54 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/259086.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 18 Jan 2010 21:50:25 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Deklaration und Definition in zwei unterschiedliche geerbte Klassen trennen. on Mon, 18 Jan 2010 21:50:25 GMT]]></title><description><![CDATA[<p>Guten Tag,<br />
obwohl ich hier neu bin, komme auch sogleich mit einem für mich großem Problem(Und ich hoffe auch ein wenig für euch, damit ich mich selbst schon mal als einen einigermaßen erfahrenen Programmierer einschätzen kann. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /> ).</p>
<p>Hier zu meinem Problem:<br />
Ich habe eine Template-Klasse Inter, welche ein Interface darstellt und eine Methode foo(UnknownType) deklariert. Des weiteren erbt diese Klasse wieder von einer anderen Spezialisierung seiner Klasse(Inter). Dadurch enthält diese Klasse später viele abstakte foo-Methoden, welche sich nur durch ihren Übergabeparametertyp unterscheiden. Als Templateargument übergibt man der Klasse eine Typliste.<br />
Da die Anzahl der Methoden erst zur Kompilierungszeit bekannt ist, muss ich auch die Implementierung variabel halten. Dies habe ich mit einer weiteren Klasse Defin versucht, welche fast genauso aufgebaut ist, wie die Klasse Inter, nur dass die Methode nicht abstrakt, sondern vollständig definiert ist.<br />
Diese beiden erstellten Klassen versuche ich nun in einer nächsten Klasse Merge zusammenzuführen, in dem sie von beiden Klassen erbt. Leider klappt dies scheinbar so nicht. Sobald ich nämlich versuche eine Instanz von Merge zu erzeugen, wird mir gesagt, dass die Klasse abstrakt sei.<br />
Als Test habe ich mal folgendes Konstrukt geschrieben, welches leider auch nicht funktioniert:</p>
<pre><code class="language-cpp">class Inter
{
public:
	virtual ~Inter() {}
	virtual void foo() = 0;
};

class Defen
{
public:
	virtual ~Defen() {}
	virtual void foo() { cout &lt;&lt; &quot;Defen&quot;; }
};

class Merged: public Defen, public Inter
{
};
</code></pre>
<p>Daher ist nun meine Frage, ob es da eine Möglichkeit gibt, dies auf eine andere Weise zu implementieren oder ob ich einfach nur irgendwo einen Fehler gemacht habe.<br />
Der Grund, warum ich das alles eigentlich mache ist, weil man in C++ keine Template-Methoden virtuell machen kann, was wohl auch seinen Grund hat ...</p>
<p>Gruß, Mickeyman.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1841025</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1841025</guid><dc:creator><![CDATA[Mickeyman]]></dc:creator><pubDate>Mon, 18 Jan 2010 21:50:25 GMT</pubDate></item><item><title><![CDATA[Reply to Deklaration und Definition in zwei unterschiedliche geerbte Klassen trennen. on Mon, 18 Jan 2010 22:25:34 GMT]]></title><description><![CDATA[<p>Mickeyman schrieb:</p>
<blockquote>
<p>Diese beiden erstellten Klassen versuche ich nun in einer nächsten Klasse Merge zusammenzuführen, in dem sie von beiden Klassen erbt. Leider klappt dies scheinbar so nicht. Sobald ich nämlich versuche eine Instanz von Merge zu erzeugen, wird mir gesagt, dass die Klasse abstrakt sei.</p>
</blockquote>
<p>Ist auch kein Wunder, schliesslich ist die Basisklasse <code>Inter</code> nach wie vor abstrakt. Dass nebenbei noch von einer anderen Klasse geerbt wird, die zufällig das gleiche Interface hat, tut nichts zur Sache.</p>
<p>Ich denke, du möchtest eher <code>Defen</code> von <code>Inter</code> ableiten, um die in <code>Inter</code> rein virtuell deklarierten Methoden zu überschreiben. Ich verstehe nicht ganz, worauf du mit der variablen Implementierung zur Compilezeit hinauswillst, aber könnte mir denken, dass du damit die vom Interface erbende Klasse leicht austauschen willst (was ja durch einfache Vererbung ohne weiteres möglich wäre). Auf jeden Fall stellt sich aber die Frage, ob <code>Merge</code> überhaupt notwendig ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1841046</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1841046</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Mon, 18 Jan 2010 22:25:34 GMT</pubDate></item><item><title><![CDATA[Reply to Deklaration und Definition in zwei unterschiedliche geerbte Klassen trennen. on Tue, 19 Jan 2010 13:05:51 GMT]]></title><description><![CDATA[<p>Danke für deine Antwort.<br />
Der Grund ist der, dass ich eine Schnittstelle mit ganz vielen exchanger-Methoden habe, die sich nur durch einen Übergabeparametertyp unterscheiden. Auch die Implementierungen dessen sind nahezu alle gleich. Derzeit habe ich auch redundant jede Methode einzeln aufgeschrieben. Um diese Redundanz zu vermeiden versuche ich jetzt jedoch, es mit generischer Programmierung zu umgehen. Denn es könnten jederzeit neue Typen hinzukommen, sowie Änderungen an den bestehenden Methoden vorgenommen werden. Vor allem die Änderungen sind derzeit extrem aufwändig.<br />
Daher hier mal ein etwas konkreteres Beispiel, das ich nach dem neuen Muster von Nexus gemacht habe. Leider gibt es dabei das Problem, dass er nur die Methode aus der ersten Basisklasse erkennt. Des weiteren gibt es noch das Problem, dass das eigentliche Interface für den Compiler nicht mehr klar erkennbar ist.<br />
Hier der Code:</p>
<pre><code class="language-cpp">template&lt;typename typelist&gt;
class GenericInterface;

template&lt;typename T1, typename T2&gt;
class GenericInterface&lt; Typelist&lt;T1,T2&gt; &gt;: public GenericInterface&lt;T2&gt;
{
public:
	typedef T1 CurrType;

public:
	virtual ~GenericInterface() {}
	virtual void exchange(T1 value) = 0;
};

template&lt;&gt;
class GenericInterface&lt; Nulltype &gt;
{
};

//---------------------------------------------------

template&lt;typename typelist&gt;
class Exchanger;

template&lt;typename T1, typename T2&gt;
class Exchanger&lt; Typelist&lt;T1,T2&gt; &gt;: public GenericInterface&lt; Typelist&lt;T1, Nulltype&gt; &gt;, public Exchanger&lt;T2&gt;
{
public:
	typedef T1 CurrType;

public:
	virtual ~Exchanger() {}
	void exchange(T1 value)
	{
		std::cout &lt;&lt; value &lt;&lt; std::endl;
	}
};

template&lt;&gt;
class Exchanger&lt; Nulltype &gt;
{
};

//---------------------------------------------------
//---------------------------------------------------

int main ()
{
	typedef Typelist&lt;char, Typelist&lt;bool, Typelist&lt;int, Nulltype&gt; &gt; &gt; MyTypelist;
	typedef GenericInterface&lt;MyTypelist&gt; SpezInterface;
	typedef Exchanger&lt;MyTypelist&gt; SpezExchanger;

	SpezExchanger ex;
	// Leider erkennt er hier nur exchange(char).
	ex.exchange(1324); // Warning

	// Wie oben schon beschrieben, erkennt er hier das Interface nicht.
	SpezInterface* interface1 = &amp;ex; // Error

	return 0;
}
</code></pre>
<p>Ich hoffe, dass es nun ein wenig verständlicher geworden ist.<br />
Es könnte natürlich auch sein, dass es dazu keine Lösung gibt. Sollte dies derzeit wirklich nicht lösbar sein, dann würde ich gerne noch wissen, ob es denn im neuen C++0x machbar wäre?</p>
<p>Gruß, Mickeyman.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1841367</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1841367</guid><dc:creator><![CDATA[Mickeyman]]></dc:creator><pubDate>Tue, 19 Jan 2010 13:05:51 GMT</pubDate></item><item><title><![CDATA[Reply to Deklaration und Definition in zwei unterschiedliche geerbte Klassen trennen. on Tue, 19 Jan 2010 14:48:01 GMT]]></title><description><![CDATA[<p>Mickeyman schrieb:</p>
<blockquote>
<p>Um diese Redundanz zu vermeiden versuche ich jetzt jedoch, es mit generischer Programmierung zu umgehen.</p>
</blockquote>
<p>Richtiger Ansatz, Codeduplizierung zu vermeiden ist immer gut. <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>Also zum Problem. Ich habe mit deinem Code herumexperimentiert und denke, nun sollte es laufen. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Ein Problem bei dir war, dass jede <code>exchange()</code> -Funktion diejenige der Basisklasse gerade wieder verdeckte. Mittels <code>using</code> kann das aufgelöst werden. Dazu muss aber eine entsprechende Methode in der Basisklasse vorhanden sein, auch in der letzten Instanziierung. Um dies zu erreichen, habe ich eine Templatespezialisierung für <code>Typelist&lt;T1, Nulltype&gt;</code> eingerichtet und dort kein <code>using</code> mehr benutzt. Die Spezialisierung <code>GenericInterface&lt;NullType&gt;</code> entfällt somit, da leere Typlisten schon wegen <code>Exchanger</code> nicht erlaubt sind.</p>
<pre><code class="language-cpp">template &lt;typename T1, typename T2&gt; 
class GenericInterface&lt; Typelist&lt;T1,T2&gt; &gt; : public GenericInterface&lt;T2&gt; 
{ 
public:
	using GenericInterface&lt;T2&gt;::exchange;
    virtual void exchange(T1 value) = 0; 
}; 

template &lt;typename T1&gt;
class GenericInterface&lt; Typelist&lt;T1,Nulltype&gt; &gt;
{
public:
	virtual ~GenericInterface() {};
	virtual void exchange(T1 value) = 0;
};
</code></pre>
<p>Soviel dazu. Nun aber zum interessanten Teil. In deinem Code hast du in jeder Instanziierung von <code>Exchanger</code> von <code>GenericInterface&lt;T1,Nulltype&gt;</code> abgeleitet. Das ist einerseits unnötig, andererseits kann so die Vererbungsbeziehung nicht hergestellt werden, weil es sich eben um eine andere Klasse handelt. Bedenke, dass in deiner Implementierung das Template <code>GenericInterface</code> jeweils mit einer 1-elementigen Typliste instanziiert wird.</p>
<p>Doch wie kann man diesem Problem begegnen? Naheliegend wäre es, nur einmal von <code>GenericInterface</code> abzuleiten, dafür mit der gesamten Typliste. Es stellt sich jedoch die Frage, wann dies geschehen soll. Bei der ersten Instanziierung, also in der obersten Rekursionsebene? Sicherlich nicht, denn die Basisklasse muss ja bekannt sein, wenn die Methoden überschrieben werden. Da die Instanziierungen für jeden konkreten Typ ( <code>char</code> , <code>bool</code> , <code>int</code> in deiner Typliste) von <code>GenericInterface</code> erben müssen, kommt eigentlich nur eine Möglichkeit in Frage: <code>GenericInterface</code> muss am Ende der Vererbungskette stehen. Da die Typliste mit zunehmender Vererbungstiefe immer kleiner wird und am Schluss leer ist, muss man sich jedoch überlegen, mit welcher Typliste man nun <code>GenericInterface</code> instanziiert. Dazu habe ich einen zweiten Template-Parameter mit einer unveränderlichen Typliste gewählt, welcher die Originalinformation durch alle Klassen trägt.</p>
<pre><code class="language-cpp">template&lt;typename TL&gt; 
class Exchanger; 

template &lt;typename T1, typename T2&gt; 
class Exchanger&lt; Typelist&lt;T1,T2&gt; &gt; : public ExchangerImpl&lt; Typelist&lt;T1,T2&gt;, Typelist&lt;T1,T2&gt; &gt;
{ 
public: 
    typedef T1 CurrType;
};
</code></pre>
<p>Wie du siehst, findet der eigentliche Kern nicht in <code>Exchanger</code> statt, sondern in <code>ExchangerImpl</code> . Ich habe diesen Weg gewählt, weil so die öffentliche Schnittstelle (in diesem Falle das Template <code>Exchanger</code> ) nur relevante Templateparameter enthält. <code>ExchangerImpl</code> sieht so aus:</p>
<pre><code class="language-cpp">template &lt;typename RemainingTL, typename WholeTL&gt;
class ExchangerImpl;

template &lt;typename T1, typename T2, typename WholeTL&gt;
class ExchangerImpl&lt; Typelist&lt;T1,T2&gt;, WholeTL &gt; : public ExchangerImpl&lt; T2, WholeTL &gt;
{
public:
	using ExchangerImpl&lt;T2, WholeTL&gt;::exchange;

	void exchange(T1 value) 
    { 
        std::cout &lt;&lt; value &lt;&lt; std::endl; 
    } 
};

template &lt;typename WholeTL&gt;
class ExchangerImpl&lt; Nulltype, WholeTL &gt; : public GenericInterface&lt; WholeTL &gt;
{ 
};
</code></pre>
<p>Ich hoffe, ich konnte dir bei deinem Problem helfen. Ich muss aber sagen, dieser Thread enthält für mich eine der interessanteren Problemstellungen dieses Forums. Template-Metaprogrammierung sieht man hier eher selten. <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/1841417</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1841417</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Tue, 19 Jan 2010 14:48:01 GMT</pubDate></item><item><title><![CDATA[Reply to Deklaration und Definition in zwei unterschiedliche geerbte Klassen trennen. on Tue, 19 Jan 2010 14:59:54 GMT]]></title><description><![CDATA[<p>Das ist ja super! Klappt wunderbar.<br />
Danke für deine so schnelle Hilfe. Das wird wohl mein Codevolumen so um die 80% und steigend verringern! Und von der Wartbarkeit braucht man erst gar nicht zu sprechen. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Vielleicht werde ich dir zu liebe irgendwann wieder etwas über Metaprogrammierung posten. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1841452</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1841452</guid><dc:creator><![CDATA[Mickeyman]]></dc:creator><pubDate>Tue, 19 Jan 2010 14:59:54 GMT</pubDate></item><item><title><![CDATA[Reply to Deklaration und Definition in zwei unterschiedliche geerbte Klassen trennen. on Tue, 19 Jan 2010 18:55:55 GMT]]></title><description><![CDATA[<p>Das Ganze kann noch etwas verfeinert werden, indem die eigentliche Implementation von den technischen Artefakten, die für die Vererbung gebraucht werden, getrennt wird:</p>
<pre><code class="language-cpp">#include &lt;boost/mpl/vector.hpp&gt;
#include &lt;boost/mpl/inherit_linearly.hpp&gt;
#include &lt;boost/mpl/empty_base.hpp&gt;
#include &lt;boost/mpl/placeholders.hpp&gt;

template &lt;typename T&gt;
class Exchanger
{
public:
    virtual ~Exchanger() {}
    virtual void exchange(T) {}
};

template &lt;typename T1, typename T2&gt;
class ExchangerNode : public T1, public Exchanger&lt;T2&gt;
{
public:
    using T1::exchange;
    using Exchanger&lt;T2&gt;::exchange;
};
template &lt;typename T&gt;
class ExchangerNode&lt;boost::mpl::empty_base,T&gt; : public Exchanger&lt;T&gt;
{};

template &lt;typename T1,            typename T2 = boost::mpl::na, typename T3 = boost::mpl::na,
    typename T4 = boost::mpl::na, typename T5 = boost::mpl::na, typename T6 = boost::mpl::na,
    typename T7 = boost::mpl::na, typename T8 = boost::mpl::na, typename T9 = boost::mpl::na&gt;
class Interface : public boost::mpl::inherit_linearly&lt;
    boost::mpl::vector&lt;T1,T2,T3,T4,T5,T6,T7,T8,T9&gt;,
    ExchangerNode&lt;boost::mpl::placeholders::_1, boost::mpl::placeholders::_2&gt; &gt;::type
{};

int main()
{
    Interface&lt;wchar_t*,char*&gt; i;
    i.exchange(&quot;&quot;);
    i.exchange(L&quot;&quot;);
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1841582</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1841582</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Tue, 19 Jan 2010 18:55:55 GMT</pubDate></item><item><title><![CDATA[Reply to Deklaration und Definition in zwei unterschiedliche geerbte Klassen trennen. on Fri, 22 Jan 2010 13:49:07 GMT]]></title><description><![CDATA[<p>Danke für die Alternative.<br />
Allerdings muss ich sagen, dass ich die nicht so ganz verstehe. Ich sehe nirgends die Vererbung von Interface. Es geht dort scheinbar eher anders herum. Das das Interface von der Implementierung erbt. Vielleicht irre ich mich da aber auch. Habe immer die Boost-Lib gemieden.<br />
Es dürfte da aber wohl noch ein Problem geben. Und zwar kann es bei mir so bis zu 100 verschiedene Typen geben. Ich glaube nicht, dass man so viele Templateparameter übergeben kann, sondern nur über eine Typliste.</p>
<p>Gruß, Mickeyman.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1843284</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1843284</guid><dc:creator><![CDATA[Mickeyman]]></dc:creator><pubDate>Fri, 22 Jan 2010 13:49:07 GMT</pubDate></item></channel></rss>