<?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[=-Operator bei Vererbung]]></title><description><![CDATA[<p>In folgendem Programm weigert sich der Compiler unten in Zeile 18, den =-Operator aufzurufen. Warum ist das so? Können Operatoren nicht vererbt werden, ohne sie in der abgeleiteten Klasse noch mal explizit neu zu deklarieren? Wenn ich in Zeile 16 nämlich Derived durch Base ersetze, funktioniert es.</p>
<pre><code class="language-cpp">class Base
{
public:
	virtual int operator = (int value)
	{
		return value;
	}
};

class Derived : public Base
{
};

int main()
{
	Derived d;

	d = 5;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/270167/operator-bei-vererbung</link><generator>RSS for Node</generator><lastBuildDate>Sun, 30 Aug 2026 11:13:03 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/270167.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 07 Jul 2010 15:50:09 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to =-Operator bei Vererbung on Wed, 07 Jul 2010 15:50:09 GMT]]></title><description><![CDATA[<p>In folgendem Programm weigert sich der Compiler unten in Zeile 18, den =-Operator aufzurufen. Warum ist das so? Können Operatoren nicht vererbt werden, ohne sie in der abgeleiteten Klasse noch mal explizit neu zu deklarieren? Wenn ich in Zeile 16 nämlich Derived durch Base ersetze, funktioniert es.</p>
<pre><code class="language-cpp">class Base
{
public:
	virtual int operator = (int value)
	{
		return value;
	}
};

class Derived : public Base
{
};

int main()
{
	Derived d;

	d = 5;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1922825</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1922825</guid><dc:creator><![CDATA[Jimmbob]]></dc:creator><pubDate>Wed, 07 Jul 2010 15:50:09 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Wed, 07 Jul 2010 15:59:38 GMT]]></title><description><![CDATA[<p>Problem ist, dass jede Klasse automatisch einen <code>operator=</code> zur Verfügung stellt. In Derived steht somit ein <code>Derived&amp; operator =(Derived const&amp;)</code> bereits zur Verfügung. Dieser überdeckt den <code>operator =</code> aus Base. Daher gibt es keinen gültigen <code>operator =</code> . Was du in dem Fall tun musst, ist den <code>operator =</code> aus <code>Base</code> raufzuziehen, damit er bei der Auflösung überhaupt in Betracht gezogen wird.</p>
<pre><code class="language-cpp">class Base
{
public:
    virtual int operator = (int value)
    {
        return value;
    }
};

class Derived : public Base
{
public:
    using Base::operator =;
};

int main()
{
    Derived d;

    d = 5;
}
</code></pre>
<p>Jetzt sollte es gehen.</p>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1922828</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1922828</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Wed, 07 Jul 2010 15:59:38 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Wed, 07 Jul 2010 16:14:35 GMT]]></title><description><![CDATA[<p>Aber <code>Derived &amp;operator =(Derived const &amp;)[/cpp] hat ja eine andere Signatur als [c]int operator =(int)</code> . Wieso verdeckt der eine dann den anderen? Selbst wenn es diesen implizit vorhandenen Operator in Derived schon gibt, dürfte sich der ja mit dem aus Base kommenden Operator gar nicht in die Quere kommen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1922838</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1922838</guid><dc:creator><![CDATA[Jimmbob]]></dc:creator><pubDate>Wed, 07 Jul 2010 16:14:35 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Wed, 07 Jul 2010 16:25:06 GMT]]></title><description><![CDATA[<p>Nachtrag:<br />
Was mach ich eigentlich, wenn ich sowas hier habe (siehe Kommentare im Code):</p>
<pre><code class="language-cpp">class Base
{
public:
	virtual int operator =(int value)
	{
		return value;
	}

private:
	Base &amp;operator =(const Base &amp;value);
	// Keine Implementierung, weil so eine
	// Zuweisung nicht möglich sein soll.
};

class Derived : public Base
{
public:
	using Base::operator =;
	// Das geht jetzt nicht mehr.
};

int main()
{
	Derived d;

	d = 5;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1922843</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1922843</guid><dc:creator><![CDATA[Jimmbob]]></dc:creator><pubDate>Wed, 07 Jul 2010 16:25:06 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Wed, 07 Jul 2010 18:59:50 GMT]]></title><description><![CDATA[<p>Jimmbob schrieb:</p>
<blockquote>
<p>Aber <code>Derived &amp;operator =(Derived const &amp;)[/cpp] hat ja eine andere Signatur als [c]int operator =(int)</code> . Wieso verdeckt der eine dann den anderen? Selbst wenn es diesen implizit vorhandenen Operator in Derived schon gibt, dürfte sich der ja mit dem aus Base kommenden Operator gar nicht in die Quere kommen.</p>
</blockquote>
<p>Die Signatur spielt absolut keine Rolle. Es geht hier um den Scope, in welchem die Funktion definiert wurde. Es werden zuerst alle <code>operator=</code> in Derived gesucht. Wenn welche gefunden wurden, dann wird nicht mehr weitergesucht, sondern nur noch der beste ausgewählt. Leider gibt es aber keinen, daher gibt es einen Kompilerfehler. Wenn theoretisch kein <code>operator=</code> gefunden worden wäre, erst dann würde in Base nach <code>operator=</code> Methoden gesucht werden. So ist es halt im Standard definiert. Das gilt übrigens ganz allgemein für alle möglichen Funktionen.</p>
<p>Zu deinem zweiten Problem:<br />
Die Zuweisung ist an sich schon etwas fraglich. Normalerweise weist man einer Variable nur Werte des gleichen Typs zu. Da kommt doch etwas die Frage auf, ob eine Funktion nicht besser wäre?</p>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1922895</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1922895</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Wed, 07 Jul 2010 18:59:50 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Wed, 07 Jul 2010 23:37:26 GMT]]></title><description><![CDATA[<p>Nebenbei: Ein virtueller Zuweisungsoperator ist ein wenig fragwürdig. Und zwar einfach, weil C++ kein Double-Dispatching kann und der rechte Operand somit als statischer Typ interpretiert wird, was bei polymorphem Code wie</p>
<pre><code class="language-cpp">Base* a = ...;
Base* b = ...;

*a = *b;
</code></pre>
<p>nur die Basisklassenversion <code>Base::operator=</code> in Betracht zieht.</p>
<p>Alternativen sind oft auch semantisch sinnvoller: Entweder, man verbietet Wertsemantik komplett (durch privaten Kopierkonstruktor und Zuweisungsoperator), oder man lässt sie auf Objekten gleichen Typs (in der gleichen Hierarchiestufe) zu, wodurch man wiederum kein <code>virtual</code> benötigt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923034</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923034</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 07 Jul 2010 23:37:26 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 14:43:46 GMT]]></title><description><![CDATA[<p>Die einfachste Möglichkeit einer auch polymorph korrekt funktionierenden Zuweisung ist, in jeder Klasse einer Vererbungshierarchie den operator=() zu implementieren und in ihm eine virtuelle Funktion assign() oder zuweisung() aufzurufen, die die eigentliche Arbeit macht. Beispiel:</p>
<pre><code class="language-cpp">Derived&amp; operator=(const Derived&amp; rhs) { 
      return assign(rhs); 
   }

   virtual Derived&amp; assign(const Base&amp; rhs) {
      Derived temp(dynamic_cast&lt;const Derived&amp;&gt;(rhs));
      swap(temp);
      return *this;
   }
</code></pre>
<p>Der dynamic_cast sorgt für den richtigen Typ. Bei falscher Verwendung (= nicht passende Typen) gibt es eine Exception.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923355</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923355</guid><dc:creator><![CDATA[UBr]]></dc:creator><pubDate>Thu, 08 Jul 2010 14:43:46 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 15:01:01 GMT]]></title><description><![CDATA[<p>Ergänzung: Jede Klasse sollte auch eine Methode swap() haben, die in assign() aufgerufen wird. swap(arg) vertauscht einfach das Argument mit *this.</p>
<pre><code class="language-cpp">void swap(Derived&amp; rhs) {
      X::swap(rhs);           // Oberklassendaten
      std::swap(lokalesDatum1, rhs.lokalesDatum1);    // lokale Daten
      std::swap(lokalesDatum2, rhs.lokalesDatum2);    // lokale Daten
   }
</code></pre>
<p>X muss dabei die <strong>direkte</strong> Oberklasse von Derived sein. Falls Derived direkt von Base erbt, gilt also X=Base. Die Methode swap() ruft die entsprechende Funktion der Standardbibliothek auf.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923359</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923359</guid><dc:creator><![CDATA[UBr]]></dc:creator><pubDate>Thu, 08 Jul 2010 15:01:01 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 15:39:05 GMT]]></title><description><![CDATA[<p>UBr schrieb:</p>
<blockquote>
<p>Ergänzung: Jede Klasse sollte auch eine Methode swap() haben, die in assign() aufgerufen wird. swap(arg) vertauscht einfach das Argument mit *this.</p>
</blockquote>
<p>Warum soll man swap bei einer Zuweisung verwenden?<br />
Das macht ja dein zugewiesenes Objekt 'kaputt'</p>
<p>UBr schrieb:</p>
<blockquote>
<pre><code class="language-cpp">virtual Derived&amp; assign(const Base&amp; rhs) {
      Derived temp(dynamic_cast&lt;const Derived&amp;&gt;(rhs));
      swap(temp);
      return *this;
   }
</code></pre>
<p>Der dynamic_cast sorgt für den richtigen Typ. Bei falscher Verwendung (= nicht passende Typen) gibt es eine Exception.</p>
</blockquote>
<p>Ich persönlich würde ein static_cast verwendet, der in den meisten Fällen ausreicht.</p>
<p>EDIT: ups... Falsche Aussage gelöscht</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923369</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923369</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 08 Jul 2010 15:39:05 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 15:36:57 GMT]]></title><description><![CDATA[<p>CSpille schrieb:</p>
<blockquote>
<p>Warum soll man swap bei einer Zuweisung verwenden?<br />
Das macht ja dein zugewiesenes Objekt 'kaputt'</p>
</blockquote>
<p>Das ganze nennt sich Copy-and-Swap. Dabei wird zuerst eine Kopie des Operanden angelegt und mit der gespwapt. Vorteil: man kann den Kopierkonstruktor wiederverwenden und das ist exceptionsicher.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923378</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923378</guid><dc:creator><![CDATA[ipsec]]></dc:creator><pubDate>Thu, 08 Jul 2010 15:36:57 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 16:57:09 GMT]]></title><description><![CDATA[<p>@CSpille:</p>
<pre><code class="language-cpp">Base b;
Derived d;
b = d; // s.u.
</code></pre>
<p>So eine Zuweisung ist syntaktisch erlaubt, semantisch i.Allg. aber nicht erwünscht. Mit static_cast würde es keine Exception für diesen Fall geben. Nur wenn b=d tatsächlich erlaubt sein soll, ist static_cast besser. Ich kann mir aber keinen praktisch relevanten Anwendungsfall dafür vorstellen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923426</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923426</guid><dc:creator><![CDATA[make it right]]></dc:creator><pubDate>Thu, 08 Jul 2010 16:57:09 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 17:13:10 GMT]]></title><description><![CDATA[<p>@make it right:</p>
<p>Dessen war ich mir bewusst, jedoch würde ich die Performance bevorzugen.<br />
Im anderen Fall erhältst du ja auch nur einen Runtime-Fehler...</p>
<p>Naja...<br />
evlt. dynamic_cast für Debug und static_cast für Release</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923432</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923432</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 08 Jul 2010 17:13:10 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 18:38:12 GMT]]></title><description><![CDATA[<p>CSpille schrieb:</p>
<blockquote>
<p>@make it right:</p>
<p>Dessen war ich mir bewusst, jedoch würde ich die Performance bevorzugen.<br />
Im anderen Fall erhältst du ja auch nur einen Runtime-Fehler...</p>
</blockquote>
<p>Nicht unbedingt - hängt vom nachfolgenden Code ab. Der Performance-Unterschied ist minimal, weil der Laufzeitaufwand gegenüber dem Kopierkonstruktor (erst recht bei dynamischen Daten) praktisch keine Rolle spielt. Die Performance sollte man da optimieren, wo sie wirklich (=messbar!) aufgefressen wird.</p>
<p>CSpille schrieb:</p>
<blockquote>
<p>Naja...<br />
evlt. dynamic_cast für Debug und static_cast für Release</p>
</blockquote>
<p>Wie soll man das pragmatisch und wartungsfreundlich realisieren?<br />
Ist es sinnvoll, dass ein Programm sich möglicherweise bei Debug und Release jeweils verschieden verhält?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923483</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923483</guid><dc:creator><![CDATA[make it right]]></dc:creator><pubDate>Thu, 08 Jul 2010 18:38:12 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 18:41:38 GMT]]></title><description><![CDATA[<p>make it right schrieb:</p>
<blockquote>
<p>@CSpille:</p>
<pre><code class="language-cpp">Base b;
Derived d;
b = d; // s.u.
</code></pre>
<p>So eine Zuweisung ist syntaktisch erlaubt, semantisch i.Allg. aber nicht erwünscht. Mit static_cast würde es keine Exception für diesen Fall geben. Nur wenn b=d tatsächlich erlaubt sein soll, ist static_cast besser. Ich kann mir aber keinen praktisch relevanten Anwendungsfall dafür vorstellen.</p>
</blockquote>
<p>Welche Exception?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923487</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923487</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 08 Jul 2010 18:41:38 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 18:44:58 GMT]]></title><description><![CDATA[<p>make it right schrieb:</p>
<blockquote>
<p>Ist es sinnvoll, dass ein Programm sich möglicherweise bei Debug und Release jeweils verschieden verhält?</p>
</blockquote>
<p>Ja.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923491</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923491</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 08 Jul 2010 18:44:58 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 18:55:13 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>Welche Exception?</p>
</blockquote>
<p>std::bad_cast natürlich</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923498</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923498</guid><dc:creator><![CDATA[zamborambo]]></dc:creator><pubDate>Thu, 08 Jul 2010 18:55:13 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 19:00:17 GMT]]></title><description><![CDATA[<p>make it right schrieb:</p>
<blockquote>
<p>CSpille schrieb:</p>
<blockquote>
<p>@make it right:</p>
<p>Dessen war ich mir bewusst, jedoch würde ich die Performance bevorzugen.<br />
Im anderen Fall erhältst du ja auch nur einen Runtime-Fehler...</p>
</blockquote>
<p>Nicht unbedingt - hängt vom nachfolgenden Code ab. Der Performance-Unterschied ist minimal, weil der Laufzeitaufwand gegenüber dem Kopierkonstruktor (erst recht bei dynamischen Daten) praktisch keine Rolle spielt. Die Performance sollte man da optimieren, wo sie wirklich (=messbar!) aufgefressen wird.</p>
</blockquote>
<p>Also ich persönlich habe einen dynamic_cast (ohne jemals Messungen angestellt zu<br />
haben) immer als sehr teuer angesehen. Immerhin werden (so zumindest meine Vorstellung)<br />
alle möglichen Klassen-IDs verglichen. Somit ist ein dynamic_cast wohl eine<br />
der aufwändigsten Anweisungen.</p>
<p>make it right schrieb:</p>
<blockquote>
<p>CSpille schrieb:</p>
<blockquote>
<p>Naja...<br />
evlt. dynamic_cast für Debug und static_cast für Release</p>
</blockquote>
<p>Wie soll man das pragmatisch und wartungsfreundlich realisieren?<br />
Ist es sinnvoll, dass ein Programm sich möglicherweise bei Debug und Release jeweils verschieden verhält?</p>
</blockquote>
<p>Evtl. Geschmacksache... Warum schmeißen Collection in Java unter bestimmten<br />
Umständen eine ConcurrentModificationException (auf die man sich nicht verlassen kann).<br />
Ich möchte nur Probleme aufdecken. Ich denke nicht, dass man einen solchen<br />
Mechanismus so einsetzt, dass man diese Exception (oder eben nicht) wirklich möchte</p>
<p>Optimal wäre natürlich ein Mechanismus, der zur Kompilierzeit solche Fehler aufdeckt.</p>
<p>Ich persönlich würde wahrscheinlich in meiner Basisklasse den Zuweisungskonstruktor<br />
verbieten und in der Klasse selbst von einem Template ableiten, das den<br />
Zuweisungsoperator implementiert. Falls von dieser Klasse ebenfalls abgeleitet<br />
werden kann, würde ich eine zusätzliche Klasse dazwischen packen, die<br />
alles implementiert außer den Zuweisungsoperator.</p>
<p>So hat man dann absolut keine Probleme mehr, weil nur der passende Zuweisungsoperator<br />
deklariert ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923503</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923503</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 08 Jul 2010 19:00:17 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 19:18:22 GMT]]></title><description><![CDATA[<p>CSpille schrieb:</p>
<blockquote>
<p>Also ich persönlich habe einen dynamic_cast (ohne jemals Messungen angestellt zu<br />
haben) immer als sehr teuer angesehen. Immerhin werden (so zumindest meine Vorstellung)<br />
alle möglichen Klassen-IDs verglichen. Somit ist ein dynamic_cast wohl eine<br />
der aufwändigsten Anweisungen.</p>
</blockquote>
<p>Nicht alle möglichen Klassen-IDs, sondern nur in der Vererbungshierarchie.<br />
D.h. derselbe Aufwand wie bei einem virtuellen Funktionsaufruf.</p>
<p>CSpille schrieb:</p>
<blockquote>
<p>Optimal wäre natürlich ein Mechanismus, der zur Kompilierzeit solche Fehler aufdeckt.</p>
</blockquote>
<p>Stimmt. Natürlich schwierig bei Polymorphismus ...</p>
<p>CSpille schrieb:</p>
<blockquote>
<p>Ich persönlich würde wahrscheinlich in meiner Basisklasse den Zuweisungskonstruktor<br />
verbieten und in der Klasse selbst von einem Template ableiten, das den<br />
Zuweisungsoperator implementiert. Falls von dieser Klasse ebenfalls abgeleitet<br />
werden kann, würde ich eine zusätzliche Klasse dazwischen packen, die<br />
alles implementiert außer den Zuweisungsoperator.</p>
</blockquote>
<p>Klingt komplex. Da wäre ein konkretes Beispiel interessant, um zu sehen, ob das wirklich einfacher ist als die obige Struktur mit assign/swap! Halte ich für nicht möglich, lasse mich aber gern überzeugen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923516</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923516</guid><dc:creator><![CDATA[make it right]]></dc:creator><pubDate>Thu, 08 Jul 2010 19:18:22 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 19:25:41 GMT]]></title><description><![CDATA[<p>make it right schrieb:</p>
<blockquote>
<p>D.h. derselbe Aufwand wie bei einem virtuellen Funktionsaufruf.</p>
</blockquote>
<p>Das glaube ich jetzt mal nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923525</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923525</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Thu, 08 Jul 2010 19:25:41 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 19:32:03 GMT]]></title><description><![CDATA[<p>de scha wü?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923531</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923531</guid><dc:creator><![CDATA[ssssxxxxxxxxaaaaaaa]]></dc:creator><pubDate>Thu, 08 Jul 2010 19:32:03 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Thu, 08 Jul 2010 20:30:23 GMT]]></title><description><![CDATA[<p>make it right schrieb:</p>
<blockquote>
<p>Klingt komplex. Da wäre ein konkretes Beispiel interessant, um zu sehen, ob das wirklich einfacher ist als die obige Struktur mit assign/swap! Halte ich für nicht möglich, lasse mich aber gern überzeugen.</p>
</blockquote>
<p>Ist auch komplex, aber du hast deinen Fehler zur Kompilierzeit</p>
<p>Hier ein Beispiel:</p>
<pre><code class="language-cpp">#include&lt;iostream&gt;

template&lt;typename T&gt;
class Assignable{
public:
        T&amp; assign(const T&amp; t){
                T temp(t);
                T&amp; tRef = static_cast&lt;T&amp;&gt;(*this);
                swap(tRef, temp);
                return tRef;
        }
};

class IA {
public:
        int a;
private:
        IA&amp; operator=(const IA&amp; a);
};

class IB : public IA{
public:
        int b;
private:
        IB&amp; operator=(const IB&amp; a);
};

class A :public IA, public Assignable&lt;A&gt;{
public:
        A&amp; operator=(const A&amp; t){
                return assign(t);
        }
};

class B :public IB, public Assignable&lt;B&gt;{
public:
        B&amp; operator=(const B&amp; t){
                return assign(t);
        }
};

void swapInternal(IA&amp; a, IA&amp; b){
        std::swap(a.a, b.a);
}

void swap(A&amp; a, A&amp; b){
        swapInternal(a,b);
}

void swap(B&amp; a, B&amp; b){
        swapInternal(a, b);
        std::swap(a.b, b.b);
}

int main(){
        A a;
        a.a = 1;
        B b;;
        b.a = 1;
        b.b = 1;
        A a2;
        a2 = a;
        B b2;
        b2 = b;
        // b2 = static_cast&lt;IB&amp;&gt;(b); &lt;- Das geht dann nicht!!!
        return 0;
}
</code></pre>
<p>Die Frage, ob man sich den Aufwand macht, ist natürlich Geschmacksache,<br />
jedoch hat man eine wirklich saubere Schnittstelle...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923566</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923566</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 08 Jul 2010 20:30:23 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Fri, 09 Jul 2010 07:29:23 GMT]]></title><description><![CDATA[<p>Es ging ja darum, eine polymorphe Zuweisung zu ermöglichen.<br />
Das geht mit deinem Beispiel nicht. Ergänze dein main-Programm um</p>
<pre><code class="language-cpp">IB&amp; ibref = b2;   // legales C++
        B b3;
        b3.a = 4;
        b3.b = 5;
        ibref = b3;       // nicht möglich mit deinem Modell
        IA&amp; iaref = b2;   // legales C++
        iaref = b3;       // geht auch nicht
</code></pre>
<p>Das andere Modell von oben ist nicht nur einfacher, es hat auch kein Problem mit polymorpher Zuweisung, static_cast hin oder dynamic_cast her.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923695</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923695</guid><dc:creator><![CDATA[make it right]]></dc:creator><pubDate>Fri, 09 Jul 2010 07:29:23 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Fri, 09 Jul 2010 08:59:04 GMT]]></title><description><![CDATA[<p>Klar kannst du keiner Schnittstellen-Definition eine konkrete Instanz zuweisen<br />
oder andersrum. Deswegen ist mein Ziel eine solche Zuweisung zu verhindern.</p>
<p>Wenn du einer abgeleiteten Klasse eine Basisklasse zuweist kannst du natürlich<br />
deren Felder kopieren, aber die zusätzlichen Felder haben ja einen Einfluß auf<br />
das Verhalten der Klasse und werden weiterhin in irgendeiner Art und Weise<br />
berücksichtigt.</p>
<p>Ich kann einer Banane die Kalorien etc. eines anderen Obst (z.B. Apfel) zuweisen,<br />
jedoch bleibt sie immer noch eine Banane.<br />
Andersrum kann ich einem Obst die Kalorien einer Banane zuweisen, jedoch bleibt<br />
mein Objekt immer noch z.B. ein Apfel.</p>
<p>Ich kann ja nicht das komplette Objekt 'transformieren'. Wenn man sowas machen<br />
würde/könnte, hätte man plötzlich in seinen Korb mit Äpfeln eine Banane...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923740</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923740</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 09 Jul 2010 08:59:04 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Fri, 09 Jul 2010 09:37:14 GMT]]></title><description><![CDATA[<p>Alles Banane. ibref hat den <strong>statischen</strong> Typ IB (Sicht des Compilers), aber den <strong>dynamischen</strong> Typ B (Sicht zur Laufzeit). Unterschiedliche statische und dynamische Typen sind gerade ein Wesenszug des Polymorphismus!! (nachlesen!!!). Damit repräsentiert die Referenz ibref ein vollwertiges B-Objekt, dem man selbstverständlich ein anderes B-Objekt zuweisen kann. Also Apfel = Apfel.<br />
Und für eine nicht-virtuelle Zuweisung braucht man keine Extra-Templates.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923765</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923765</guid><dc:creator><![CDATA[zamborambo]]></dc:creator><pubDate>Fri, 09 Jul 2010 09:37:14 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Sat, 10 Jul 2010 15:24:45 GMT]]></title><description><![CDATA[<p>Man könnte denken, dass ein virtueller Zuweisungsoperator genügen würde. Das ist nicht der Fall, weil der Zuweisungsoperator anders als &quot;normale&quot; virtuelle Funktionen aufgerufen wird. Wenn nur ein virtueller Zuweisungsoperator geschrieben wurde, wird bei der Compilation der nicht-virtuelle automatisch auch noch erzeugt - und ggf. statt des virtuellen aufgerufen (siehe Abschnitt 13.5.3 im Standardentwurf). Das ist kein Problem, wenn die abgeleitete Klasse keinerlei dynamische Daten hat. Wenn es jedoch Zeigerattribute gibt, denen mit new etwas zugewiesen wird, ist ein selbstgeschriebener nicht-virtueller Zuweisungsoperator unumgänglich, weil der compilergenerierte nur den Zeiger kopieren würde, ohne Speicherplatz zu beschaffen.</p>
<p>Damit scheint es am einfachsten, den Zuweisungsoperator bei dynamischen Attributen in jeder Klasse der Vererbungshierarchie zu definieren und in ihm eine virtuelle Methode assign() aufzurufen. Weil der polymorphe Aufruf dafür sorgt, dass sowieso die richtige der überschriebenen assign()-Methoden aufgerufen wird, reicht ein static_cast! In diesem Punkt hat CSpille recht. Der dynamic_cast wirft im Zuweisungsoperator keine Exception bei der Zuweisung</p>
<pre><code class="language-cpp">base = derived;
</code></pre>
<p>weil der Typ ja stimmt. Das Problem liegt woanders: In C++ ist diese Zuweisung erlaubt, kopiert wird aber nur der Basisklassenanteil (object slicing). Die Methode assign() der obersten Basisklasse sei</p>
<pre><code class="language-cpp">virtual Base&amp; assign(const Base&amp; rhs) {
      Base temp(rhs);
      swap(temp);
      return *this;
}
</code></pre>
<p>Der Kopierkonstruktor kopiert hier nur den Basisklassenanteil.<br />
Wenn sichergestellt werden soll (und nur dann!), dass die Zuweisung base = derived; als Fehler betrachtet werden soll, weil es keine sinnvolle praktische Anwendung dafür gibt (Gegenbeispiel gesucht...), müssen die Objekttypen links und rechts verglichen werden, also</p>
<pre><code class="language-cpp">virtual Base&amp; assign(const Base&amp; rhs) {
      if(typeid(*this) != typeid(rhs)) { 
         throw std::bad_typeid();
      }
      Base temp(rhs);
      swap(temp);
      return *this;
}
</code></pre>
<p>Wenn diese Typprüfung gewünscht ist, muss sie in den assign()-Methoden der abgeleiteten Klassen wiederholt werden.</p>
<p>typeid ist von der Performance her vermutlich etwa wie dynamic-cast anzusehen. Ob der Performance-Aspekt von typeid überhaupt bei der Zuweisung eine wichtige Rolle spielt, kann nur im Vergleich mit der Performance des Kopierkonstruktors beurteilt werden.</p>
<p>Ein vergleichbares Problem hat man beim Vergleichsoperator und dem Vergleich (base == derived). Ohne Typprüfung wäre der Vergleichsoperator nicht symmetrisch, d.h. (base == derived) kann true sein und das umgekehrte false (wobei dann ohne Typprüfung auf undefinierte Bereiche zugegriffen wird). Weil der Vergleich in abgeleiteten Klassen die Basisklasse einschließt, muss die Prüfung mit typeid in abgeleiteten Klassen nicht wiederholt werden; im Gegensatz zur Zuweisung, wo die Prüfung, sofern gewünscht, in jeder Klasse vorgenommen werden muss, weil assign() nicht die entsprechende Oberklassenmethode aufruft. Also etwa</p>
<pre><code class="language-cpp">virtual bool Base::operator==(const Base&amp; arg) const {
   return 
      typeid(*this) == typeid(arg) &amp;&amp;    // Zeile löschen bei nicht erwünschter Prüfung
      vergleichKlassenlokalerAttribute(arg);  // gibt bool zurück
}
</code></pre>
<p>bzw. in einer abgeleiteten Klasse</p>
<pre><code class="language-cpp">bool Derived::operator==(const Base&amp; arg) const {
   const Derived&amp; rarg = static_cast&lt;const Derived&amp;&gt;(arg);
   return X::operator==(arg) &amp;&amp;          // X = *direkte* Oberklasse (ggf. Base)
      vergleichKlassenlokalerAttribute(rarg);  // gibt bool zurück
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1924302</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1924302</guid><dc:creator><![CDATA[UBr]]></dc:creator><pubDate>Sat, 10 Jul 2010 15:24:45 GMT</pubDate></item><item><title><![CDATA[Reply to =-Operator bei Vererbung on Sat, 10 Jul 2010 16:52:02 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/15677">@UBr</a>: Durch die Zusätzliche Vererbungsschicht ohne operator= möchte ich genau<br />
diese Zuweisungsproblematik beseitigen. So eine Zuweisung ist in meinen Augen<br />
nämlich kein Runtime-Fehler. Sonst kann man auch vorher casten.</p>
<p>EDIT: In den meisten Fällen würde ich jedoch wegen des enormen Aufwandes auf ein<br />
korrekte Anwendung des Zuweisungsoperstors im Programm achten. Ich wollte nur eine<br />
theoretisch saubere Lösung vorschlagen.<br />
Einen dynamic_cast im Debug und static_cast im Release bei Verwendung<br />
eines Templates finde ich in der Regel aber ausreichend. So sieht man, wenn auch<br />
erst zur Laufzeit, dass etwas schief geht.</p>
<p>Oder willst du bei beiden nicht genau wissen von welchem Typ sie sind ^^</p>
<p>UBr schrieb:</p>
<blockquote>
<pre><code class="language-cpp">virtual Base&amp; assign(const Base&amp; rhs) {
      if(typeid(*this) != typeid(rhs)) { 
         throw std::bad_typeid();
      }
      Base temp(rhs);
      swap(temp);
      return *this;
}
</code></pre>
</blockquote>
<p>Wenn beide von der gleichen abgeleiteten Klasse sind, dann ist die Zuweisung<br />
erlaubt und kopiert nur das 'halbe' Objekt?<br />
Oder wie soll ich das verstehen?</p>
<p>Gibt es im Standard eigentlich typeid?</p>
<p>zamborambo schrieb:</p>
<blockquote>
<p>Und für eine nicht-virtuelle Zuweisung braucht man keine Extra-Templates.</p>
</blockquote>
<p>Ich denke das Template ist hier extrem sinnvoll, ansonsten bräuchte ich den<br />
Code in jeder abgeleiteten Klasse.<br />
Genau wegen des oben bestehenden Problems verwende ich Templates...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1924329</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1924329</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sat, 10 Jul 2010 16:52:02 GMT</pubDate></item></channel></rss>