<?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[Kind-Funktion]]></title><description><![CDATA[<p>Hallo,<br />
man hat zwei Klassen:</p>
<pre><code class="language-cpp">class A
{
public:
  A();
  void foo() {/* tue dies*/}
};

A::A() {foo();}
</code></pre>
<pre><code class="language-cpp">class B : public A
{
public:
  B();
  void foo() {/* tue jenes*/}
};

B::B() : A() {}
</code></pre>
<p>Wenn ich nun ein B-Objekt erstelle, wird A::foo() aufgerufen. Gibt es eine Möglichkeit, dass, wenn ich ein Objekt der Kind-Klasse erstelle, der Konstruktor auch dessen Funktion aufruft?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/308567/kind-funktion</link><generator>RSS for Node</generator><lastBuildDate>Thu, 06 Aug 2026 17:29:38 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/308567.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 28 Sep 2012 22:00:29 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Kind-Funktion on Fri, 28 Sep 2012 22:00:29 GMT]]></title><description><![CDATA[<p>Hallo,<br />
man hat zwei Klassen:</p>
<pre><code class="language-cpp">class A
{
public:
  A();
  void foo() {/* tue dies*/}
};

A::A() {foo();}
</code></pre>
<pre><code class="language-cpp">class B : public A
{
public:
  B();
  void foo() {/* tue jenes*/}
};

B::B() : A() {}
</code></pre>
<p>Wenn ich nun ein B-Objekt erstelle, wird A::foo() aufgerufen. Gibt es eine Möglichkeit, dass, wenn ich ein Objekt der Kind-Klasse erstelle, der Konstruktor auch dessen Funktion aufruft?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255421</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255421</guid><dc:creator><![CDATA[Wurstinator]]></dc:creator><pubDate>Fri, 28 Sep 2012 22:00:29 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Fri, 28 Sep 2012 22:07:36 GMT]]></title><description><![CDATA[<p>In der Hoffnung, dich richtig verstanden zu haben: das gewünschte Late Binding erreichst du in C++ über das Schlüsselwort &quot;virtual&quot;</p>
<p>also</p>
<pre><code class="language-cpp">virtual void foo();
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2255422</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255422</guid><dc:creator><![CDATA[zwutz]]></dc:creator><pubDate>Fri, 28 Sep 2012 22:07:36 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Fri, 28 Sep 2012 22:17:34 GMT]]></title><description><![CDATA[<p>Das dachte ich auch, aber virtual ändert leider nichts.<br />
Wenn es eigentlich so sein sollte, dann liegt das Problem wohl an meinem spezifischen Code.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255424</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255424</guid><dc:creator><![CDATA[Wurstinator]]></dc:creator><pubDate>Fri, 28 Sep 2012 22:17:34 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Fri, 28 Sep 2012 22:19:31 GMT]]></title><description><![CDATA[<blockquote>
<p>Gibt es eine Möglichkeit, dass, wenn ich ein Objekt der Kind-Klasse erstelle, der Konstruktor auch dessen Funktion aufruft?</p>
</blockquote>
<pre><code class="language-cpp">B::B() : A() { foo(); }
</code></pre>
<p>Vermutlich wolltest du eine andere Frage stellen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255425</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255425</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 28 Sep 2012 22:19:31 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Fri, 28 Sep 2012 22:23:07 GMT]]></title><description><![CDATA[<p>Wenn ich das mache, wird sowohl A::foo() als auch B::foo() aufgerufen. Das geht aber nicht, da A::foo() in einem B-Objekt zum Laufzeitfehler führt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255426</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255426</guid><dc:creator><![CDATA[Wurstinator]]></dc:creator><pubDate>Fri, 28 Sep 2012 22:23:07 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Fri, 28 Sep 2012 22:37:02 GMT]]></title><description><![CDATA[<p>zwutz schrieb:</p>
<blockquote>
<p>In der Hoffnung, dich richtig verstanden zu haben: das gewünschte Late Binding erreichst du in C++ über das Schlüsselwort &quot;virtual&quot;</p>
<p>also</p>
<pre><code class="language-cpp">virtual void foo();
</code></pre>
</blockquote>
<p>Das funktioniert in regulären Methoden, allerdings nicht im Konstruktor.</p>
<p>Referenzen dazu:<br />
<a href="http://www.artima.com/cppsource/nevercall.html" rel="nofollow">http://www.artima.com/cppsource/nevercall.html</a><br />
<a href="http://msdn.microsoft.com/de-de/library/s8e39b8h%28v=vs.90%29.aspx" rel="nofollow">http://msdn.microsoft.com/de-de/library/s8e39b8h(v=vs.90).aspx</a></p>
<p>Das, was der TE möchte, ist also so, wie er sich das vorstellt, im Konstruktor nicht möglich.</p>
<p>Eine Option wäre Compositing (glaube, so nannte man das :p) zu verwenden.<br />
Beispiel:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

template &lt;class Derived&gt;
class A
{
public:
    A() { reinterpret_cast&lt;Derived*&gt;(this)-&gt;Derived::foo(); }
    void foo() { std::cout &lt;&lt; &quot;A&quot; &lt;&lt; std::endl; }
};

// foo wird &quot;überladen&quot;
class B : public A&lt;B&gt;
{
public:
    B() : A() {}
    void foo() { std::cout &lt;&lt; &quot;B&quot; &lt;&lt; std::endl; }
};

// foo wird nicht &quot;überladen&quot;
class C : public A&lt;C&gt;
{
public:
    C() : A() {}
};

int main()
{
    B b; // Ausgabe &quot;B&quot;
    C c; // Ausgabe &quot;A&quot;
    return 0;
}
</code></pre>
<p>PS.:<br />
Für alte Compiler ohne &quot;Empty Base Class Optimization&quot; muss man den reinterpret_cast noch etwas anpassen, damit das 1 Zusatz-Byte mit verrechnet wird.<br />
Aber insgesamt sollte man hier wohl besser sein Design nochmal überdenken.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255427</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255427</guid><dc:creator><![CDATA[DrakoXP]]></dc:creator><pubDate>Fri, 28 Sep 2012 22:37:02 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Fri, 28 Sep 2012 23:04:01 GMT]]></title><description><![CDATA[<p>Auf ein reinterpret_cast, dass, wie du sagst, nicht einmal compilerunabhängig funktioniert, möchte ich gerne verzichten.</p>
<p>Zum Design fällt mir nichts besseres ein. <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=":/"
      alt="😕"
    /><br />
A und B sind Widgets eines GUI-Projektes. B ist das Gleiche wie A, mit dem Unterschied, dass es auch deaktiv sein kann, sodass die meisten Nutzeraktionen nicht möglich sind.<br />
Man kann sich das in etwa so vorstellen, dass A einen Member Datentyp* hat, der in einem B-Objekt, wenn dieses deaktiv ist, auf nichts zeigt und Funktionsaufrufe somit natürlich einen Fehler hervorrufen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255429</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255429</guid><dc:creator><![CDATA[Wurstinator]]></dc:creator><pubDate>Fri, 28 Sep 2012 23:04:01 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Sat, 29 Sep 2012 10:08:55 GMT]]></title><description><![CDATA[<p>verstehe ich nicht</p>
<p>wieso kann man auf den nullzeiger nicht testen? warum keine gemeinsame basisklasse für A und B?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255498</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255498</guid><dc:creator><![CDATA[[[global:former_user]]]]></dc:creator><pubDate>Sat, 29 Sep 2012 10:08:55 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Sat, 29 Sep 2012 11:33:53 GMT]]></title><description><![CDATA[<p>Wurstinator schrieb:</p>
<blockquote>
<p>A und B sind Widgets eines GUI-Projektes. B ist das Gleiche wie A, mit dem Unterschied, dass es auch deaktiv sein kann, sodass die meisten Nutzeraktionen nicht möglich sind.</p>
</blockquote>
<p>Eventuell so?</p>
<pre><code class="language-cpp">class DeactivatableWidget : public Widget
{
    Widget *other;
    bool enabled;

public:
    virtual void input()
    {
        if(enabled)
            other-&gt;input();
    }
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2255506</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255506</guid><dc:creator><![CDATA[ipsec]]></dc:creator><pubDate>Sat, 29 Sep 2012 11:33:53 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Sat, 29 Sep 2012 11:38:20 GMT]]></title><description><![CDATA[<p>Spontan faellt mir eine einfach Loesung ein (wenn auch nich unbedingt optimal): Du machst eine Zwei-Schritte Konstruktion: <code>A a; a.create()</code><br />
<code>create</code> wuerde dann das korrekte <code>foo</code> aufrufen.</p>
<p>Aber wozu brauchst du eigentlich <code>foo</code> ?<br />
<code>foo</code> scheint bei dir eine Funktion zu sein, die in jeder abgeleiteten Klasse implementiert wird, und dann bei der Konstruktion aufgerufen werden soll.<br />
Es geht auch einfacher: Pack alles, was in <code>foo</code> steht direkt in die Konstruktoren der abgeleiteten Klassen ein.<br />
Oder hab ich was missverstanden?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255507</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255507</guid><dc:creator><![CDATA[Ferris]]></dc:creator><pubDate>Sat, 29 Sep 2012 11:38:20 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Sat, 29 Sep 2012 12:22:23 GMT]]></title><description><![CDATA[<p>Wurstinator schrieb:</p>
<blockquote>
<p>Wenn ich das mache, wird sowohl A::foo() als auch B::foo() aufgerufen. Das geht aber nicht, da A::foo() in einem B-Objekt zum Laufzeitfehler führt.</p>
</blockquote>
<p>Verstehe ich das richtig? Es darf immer nur die foo der Klasse aufgerufen werden, von der du gerade eine Instanz erstellst:<br />
- A &lt;-- B &lt;-- C<br />
- Erzeugst du eine A-Instanz soll nur A::foo aufgerufen werden.<br />
- Erezugst du eine B-Instanz soll nur B::foo aufgerufen werden.<br />
- Erezugst du eine C-Instanz soll nur C::foo aufgerufen werden.</p>
<p>Also so was?</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

class A
{
	public:
		static A create_new_A()
		{
			A a;
			a.foo();
			return a;
		}
		virtual void foo()
		{
			cout &lt;&lt; &quot;foo A&quot;;
		}
};

class B : public A
{
	public:
		static B create_new_B()
		{
			B b;
			b.foo();
			return b;
		}
		virtual void foo()
		{
			cout &lt;&lt; &quot;foo B&quot;;
		}
};

class C : public B
{
	public:
		static C create_new_C()
		{
			C c;
			c.foo();
			return c;
		}
		virtual void foo()
		{
			cout &lt;&lt; &quot;foo C&quot;;
		}
};

int main()
{
	A a = A::create_new_A();
	B b = B::create_new_B();
	C c = C::create_new_C();
}
</code></pre>
<p>Wohl ein Designfehler. Das sieht irgendwie grausig aus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255513</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255513</guid><dc:creator><![CDATA[out]]></dc:creator><pubDate>Sat, 29 Sep 2012 12:22:23 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Sat, 29 Sep 2012 14:43:15 GMT]]></title><description><![CDATA[<p>Wurstinator schrieb:</p>
<blockquote>
<p>Wenn ich das mache, wird sowohl A::foo() als auch B::foo() aufgerufen. Das geht aber nicht, da A::foo() in einem B-Objekt zum Laufzeitfehler führt.</p>
</blockquote>
<p>Das ist aber ziemlich doof, weil ein B dann nicht als A verwendet werden kann, und Du damit das LSP verletzt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255547</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255547</guid><dc:creator><![CDATA[Tachyon]]></dc:creator><pubDate>Sat, 29 Sep 2012 14:43:15 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Sat, 29 Sep 2012 18:35:11 GMT]]></title><description><![CDATA[<p>@ trustee: Ich sagte &quot;man kann sich das so vorstellen&quot;. Genau sieht es im Programm so aus, dass A einen Verweis auf einen Datentyp hat, der widerrum einen Array-Index enthält. Ist B deaktiviert, kann dieser Array-Index im Datentyp uninitialisiert sein.</p>
<p>@ ipsec: Hm, ich müsste DeactivatableWidget dann natürlich noch zum friend machen, aber ansonsten gefällt mir der Vorschlag gut. Ich denke nochmal genauer darüber nach, ob damit alles funktioniert, und nutze ihn dann eventuell.</p>
<p>@ Ferris: Es geht mir nicht nur darum, dass der Code speziell für die abgeleitete Klasse aufgerufen werden soll, sondern auch darum, dass der Code der Elternklasse <strong>nicht</strong> aufgerufen wird.</p>
<p>@ Ferris &amp; out: Klar, mit einer mehrbefehligen Konstruktion oder einer statischen Funktion geht es natürlich, aber wie ihr sagt, ist das doof; daher will ich einen anderen Weg finden.</p>
<p>@ Tachyon: Das lässt sich ja einfach lösen, wenn man so etwas wie das macht:</p>
<pre><code class="language-cpp">void A::foo()
{
  if (!is_derived())
  {
    // tue dies
  }
}
</code></pre>
<p>Nur eben im Konstruktor funktioniert das nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255599</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255599</guid><dc:creator><![CDATA[Wurstinator]]></dc:creator><pubDate>Sat, 29 Sep 2012 18:35:11 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Sat, 29 Sep 2012 19:16:37 GMT]]></title><description><![CDATA[<p>Wurstinator schrieb:</p>
<blockquote>
<p>@ Tachyon: Das lässt sich ja einfach lösen, wenn man so etwas wie das macht:</p>
</blockquote>
<p>Sobald du von einer konkreten Klasse ableitest, wird das LSP verletzt - auf irgendwelche Implementationsdetails kommt es gar nicht an. Ich verstehe nicht, wieso nach 20 Jahre Frameworks immer noch nach Prinzipien designed werden, die weder theoretisch noch praktisch wirklich funktionieren.</p>
<p>Wenn es nur darum geht, eine bestimmte Funktion nicht aus dem Basisklassenkonstruktor heraus aufzurufen: was spricht dagegen, einfach einen eigenen (protected) Konstruktor für diesen Zweck in der Basisklasse zu implementieren?</p>
<p>Alternativ könnte man auch A durch B implementieren: ein Widget, das grundsätzlich sowohl inaktiv als auch aktiv sein kann, kann ja ohne weiteres auch eines repräsentieren, welches (zufällig) immer aktiv ist. Umgekehrt gilt das aber gerade nicht.<br />
Oder aber A wird aufgeteilt in einen vererbbaren abstrakten Teil, von dem auch B erben kann, und einen Rest (der sich ggf. im entsprechenden Konstruktor erschöpft).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255614</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255614</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sat, 29 Sep 2012 19:16:37 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Sun, 30 Sep 2012 10:15:54 GMT]]></title><description><![CDATA[<p>Hm, dann verstehe ich das LSP wohl nicht richtig.</p>
<blockquote>
<p>Wenn es nur darum geht, eine bestimmte Funktion nicht aus dem Basisklassenkonstruktor heraus aufzurufen: was spricht dagegen, einfach einen eigenen (protected) Konstruktor für diesen Zweck in der Basisklasse zu implementieren?</p>
</blockquote>
<p>Wie soll das funktionieren? Ich kann ja nicht einfach einen zweiten Konstruktor mit dem gleichen Funktionsheader erstellen, oder?</p>
<blockquote>
<p>Alternativ könnte man auch A durch B implementieren</p>
</blockquote>
<p>Hm, ist zwar naheliegend, bin ich aber nicht drauf gekommen. Ich werd mir diese Möglichkeit mal durch den Kopf gehen lassen.</p>
<blockquote>
<p>Oder aber A wird aufgeteilt in einen vererbbaren abstrakten Teil, von dem auch B erben kann, und einen Rest (der sich ggf. im entsprechenden Konstruktor erschöpft).</p>
</blockquote>
<p>Versteh ich nicht <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=":/"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2255728</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255728</guid><dc:creator><![CDATA[Wurstinator]]></dc:creator><pubDate>Sun, 30 Sep 2012 10:15:54 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Sun, 30 Sep 2012 13:26:03 GMT]]></title><description><![CDATA[<p>Wurstinator schrieb:</p>
<blockquote>
<p>Hm, dann verstehe ich das LSP wohl nicht richtig.</p>
<blockquote>
<p>Wenn es nur darum geht, eine bestimmte Funktion nicht aus dem Basisklassenkonstruktor heraus aufzurufen: was spricht dagegen, einfach einen eigenen (protected) Konstruktor für diesen Zweck in der Basisklasse zu implementieren?</p>
</blockquote>
<p>Wie soll das funktionieren? Ich kann ja nicht einfach einen zweiten Konstruktor mit dem gleichen Funktionsheader erstellen, oder?</p>
</blockquote>
<p>Niemand zwingt dich, die gleiche Signatur zu verwenden</p>
<pre><code class="language-cpp">struct A
{
    void foo();
    A() { foo(); }
protected:
    struct no_foo_tag {};
    A(no_foo_tag) {};
};

struct B : A
{
    B() : A(no_foo_tag()) { foo(); }
    void foo();
};
</code></pre>
<p>Wurstinator schrieb:</p>
<blockquote>
<blockquote>
<p>Oder aber A wird aufgeteilt in einen vererbbaren abstrakten Teil, von dem auch B erben kann, und einen Rest (der sich ggf. im entsprechenden Konstruktor erschöpft).</p>
</blockquote>
<p>Versteh ich nicht <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=":/"
      alt="😕"
    /></p>
</blockquote>
<p>Im einfachsten Fall sieht das ungefähr so aus:</p>
<pre><code class="language-cpp">class widget_base
{
public:
     virtual widget_base() = 0; // pure nicht zwingend
protected:
     widget_base() { ... }
... // der wiederverwendbare Teil des widget-codes
};

class A : public widget_base
{
    A() : widget_base() { foo(); }
    void foo();
...
};

class B : public widget_base
{
    B() : widget_base() { foo(); }
    void foo();
...
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2255776</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2255776</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 30 Sep 2012 13:26:03 GMT</pubDate></item><item><title><![CDATA[Reply to Kind-Funktion on Tue, 02 Oct 2012 22:22:17 GMT]]></title><description><![CDATA[<p>Ach, so meinst du das.</p>
<p>Ich denke, ich hab jetzt genug Vorschläge für Lösungen bekommen und kann mir da jetzt die beste (= am wenigsten schlechte? :p) raussuchen. Danke.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2256635</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2256635</guid><dc:creator><![CDATA[Wurstinator]]></dc:creator><pubDate>Tue, 02 Oct 2012 22:22:17 GMT</pubDate></item></channel></rss>