<?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[Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll]]></title><description><![CDATA[<p>Ich habe eine Reihe von Objekten bei denen es sich absolut anbietet sie alle über eine gemeinsame Basisklasse anzusprechen. Bei allen Anwendungen bis auf eine:</p>
<p>Angenommen die Klassen heißen: A, B, C und erben alle von Base.<br />
Dann habe ich jetzt in meinem Programm eine einzige Stelle wo ich die Instanzen von A, B, C nicht einfach polymorph über Base-Zeiger benutzen kann. Und zwar habe ich eine Funktion mit zwei Argumenten, nennen wir sie foo(Base,Base). Problem: Es gibt auch spezialisierte Funktionen von foo(), meinetwegen foo(A,B), foo(C,C). Wie entscheide ich jetzt am einfachsten, welche Funktion aufzurufen ist? Eine virtuelle Memberfunktion reicht nicht aus, da ich ja zwei Argumente habe.</p>
<p>Eine Kaskade von dynamic_casts fände ich äußerst umständlich.</p>
<p>Ich sollte noch ausdrücklich erwähnen, dass den foo()s auch die Teile der Klassen ausreichen, die in Base gemeinsam sind, d.h. statt foo(A,B) könnte es auch genausogut foo_AB(Base,Base) heißen. Entscheidend ist, dass foo_AB() einen etwas anderen Algorithmus implementiert als foo().</p>
<p>Was ist denn da die übliche Vorgehensweise? Ich kann mir nicht vorstellen, dass ich der erste mit dieser Problemstellung bin. Da gibt es doch bestimmt irgendein Entwurfsmuster welches dies elegant löst.</p>
<p>Meine bisher &quot;eleganteste&quot; Lösung:<br />
Ich verpasse den Klassen noch eine virtuelle Methode GetId(), die mir einen eindeutigen Integerwert zurück gibt. Dann habe ich in meinem Programm ein zweidimensionales Array von Zeigern auf Funktionen mit zwei Base als Parameter. Und dann benutze ich jeweils den passenden Funktionszeiger:</p>
<pre><code>Klasse   GetID
---------------
 Base      0
  A        1
  B        2

2D Array:
 |  0      1       2 
-----------------------
0|&amp;foo   &amp;foo    &amp;foo   
1|&amp;foo  &amp;foo_AA  &amp;foo_AB
2|&amp;foo  &amp;foo_BA  &amp;foo_BB

Aufruf:
Base* ptr1 = new A;
Base* ptr2 = new B;

(*Array[ptr1-&gt;GetID()][ptr2-&gt;GetID])(*ptr1,*ptr2);  // Ruft foo_AB auf
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/270266/über-basisklassenzeiger-entscheiden-welche-spezialisierte-funktion-aufgerufen-werden-soll</link><generator>RSS for Node</generator><lastBuildDate>Sun, 30 Aug 2026 12:05:09 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/270266.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 09 Jul 2010 08:51:46 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll on Fri, 09 Jul 2010 08:51:46 GMT]]></title><description><![CDATA[<p>Ich habe eine Reihe von Objekten bei denen es sich absolut anbietet sie alle über eine gemeinsame Basisklasse anzusprechen. Bei allen Anwendungen bis auf eine:</p>
<p>Angenommen die Klassen heißen: A, B, C und erben alle von Base.<br />
Dann habe ich jetzt in meinem Programm eine einzige Stelle wo ich die Instanzen von A, B, C nicht einfach polymorph über Base-Zeiger benutzen kann. Und zwar habe ich eine Funktion mit zwei Argumenten, nennen wir sie foo(Base,Base). Problem: Es gibt auch spezialisierte Funktionen von foo(), meinetwegen foo(A,B), foo(C,C). Wie entscheide ich jetzt am einfachsten, welche Funktion aufzurufen ist? Eine virtuelle Memberfunktion reicht nicht aus, da ich ja zwei Argumente habe.</p>
<p>Eine Kaskade von dynamic_casts fände ich äußerst umständlich.</p>
<p>Ich sollte noch ausdrücklich erwähnen, dass den foo()s auch die Teile der Klassen ausreichen, die in Base gemeinsam sind, d.h. statt foo(A,B) könnte es auch genausogut foo_AB(Base,Base) heißen. Entscheidend ist, dass foo_AB() einen etwas anderen Algorithmus implementiert als foo().</p>
<p>Was ist denn da die übliche Vorgehensweise? Ich kann mir nicht vorstellen, dass ich der erste mit dieser Problemstellung bin. Da gibt es doch bestimmt irgendein Entwurfsmuster welches dies elegant löst.</p>
<p>Meine bisher &quot;eleganteste&quot; Lösung:<br />
Ich verpasse den Klassen noch eine virtuelle Methode GetId(), die mir einen eindeutigen Integerwert zurück gibt. Dann habe ich in meinem Programm ein zweidimensionales Array von Zeigern auf Funktionen mit zwei Base als Parameter. Und dann benutze ich jeweils den passenden Funktionszeiger:</p>
<pre><code>Klasse   GetID
---------------
 Base      0
  A        1
  B        2

2D Array:
 |  0      1       2 
-----------------------
0|&amp;foo   &amp;foo    &amp;foo   
1|&amp;foo  &amp;foo_AA  &amp;foo_AB
2|&amp;foo  &amp;foo_BA  &amp;foo_BB

Aufruf:
Base* ptr1 = new A;
Base* ptr2 = new B;

(*Array[ptr1-&gt;GetID()][ptr2-&gt;GetID])(*ptr1,*ptr2);  // Ruft foo_AB auf
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1923736</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923736</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Fri, 09 Jul 2010 08:51:46 GMT</pubDate></item><item><title><![CDATA[Reply to Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll on Fri, 09 Jul 2010 09:55:23 GMT]]></title><description><![CDATA[<p>&quot;Eine virtuelle Memberfunktion reicht nicht aus, da ich ja zwei Argumente habe.&quot;</p>
<p>Verstehe ich nicht. Eine virtuelle Memberfunktion kann auch zwei Argumente haben. Diese Funktion kann in den Unterklassen redefiniert werden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923772</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923772</guid><dc:creator><![CDATA[Humbert]]></dc:creator><pubDate>Fri, 09 Jul 2010 09:55:23 GMT</pubDate></item><item><title><![CDATA[Reply to Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll on Fri, 09 Jul 2010 09:56:19 GMT]]></title><description><![CDATA[<p>Hi,</p>
<blockquote>
<p>Eine virtuelle Memberfunktion reicht nicht aus, da ich ja zwei Argumente habe.</p>
</blockquote>
<p>Und wenn du 2 virtuelle Memberfunktionen nimmst?</p>
<pre><code class="language-cpp">Base* a = new A;
Base* b = new B;

a-&gt;foo(b);

void A:foo(Base* b)
{
   b-&gt;fooA(this);
}
void B:fooA(Base* a)
{
  // hier fooAB()
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1923774</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923774</guid><dc:creator><![CDATA[Jockelx]]></dc:creator><pubDate>Fri, 09 Jul 2010 09:56:19 GMT</pubDate></item><item><title><![CDATA[Reply to Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll on Fri, 09 Jul 2010 10:12:45 GMT]]></title><description><![CDATA[<p>Überseh ich was oder willst du einfach nur nen Double Dispatch?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923780</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923780</guid><dc:creator><![CDATA[Michael E.]]></dc:creator><pubDate>Fri, 09 Jul 2010 10:12:45 GMT</pubDate></item><item><title><![CDATA[Reply to Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll on Fri, 09 Jul 2010 10:33:08 GMT]]></title><description><![CDATA[<p>Hi SeppJ,</p>
<p>auch wenn das folgende Beispiel nicht kompiliert, die Idee dahinter<br />
sollte klar sein...</p>
<pre><code class="language-cpp">#include&lt;iostream&gt;
#include&lt;vector&gt;

class Foo;
class Base;

class A;
class B;

class IForwardable{
public:
        virtual void forward(Foo&amp; f, Base&amp; base) = 0;
        virtual void forward(Foo&amp; f, A&amp; a) = 0;
        virtual void forward(Foo&amp; f, B&amp; b) = 0;
        virtual void forwardIt(Foo&amp; f, Base&amp; base) = 0;
};

class Base : public IForwardable{
};

class Foo{
public:
        void print(Base&amp;, Base&amp;){
                std::cout &lt;&lt; &quot;base base&quot; &lt;&lt; std::endl;
        };
        void print(Base&amp;, A&amp;){
                std::cout &lt;&lt; &quot;base a&quot; &lt;&lt; std::endl;
        };
        void print(Base&amp;, B&amp;){
                std::cout &lt;&lt; &quot;base b&quot; &lt;&lt; std::endl;
        };
        void print(A&amp;, Base&amp;){
                std::cout &lt;&lt; &quot;a base&quot; &lt;&lt; std::endl;
        };
        void print(A&amp;, A&amp;){
                std::cout &lt;&lt; &quot;a a&quot; &lt;&lt; std::endl;
        };
        void print(A&amp;, B&amp;){
                std::cout &lt;&lt; &quot;a b&quot; &lt;&lt; std::endl;
        };
        void print(B&amp;, Base&amp;){
                std::cout &lt;&lt; &quot;b base&quot; &lt;&lt; std::endl;
        };
        void print(B&amp;, A&amp;){
                std::cout &lt;&lt; &quot;b a&quot; &lt;&lt; std::endl;
        };
        void print(B&amp;, B&amp;){
                std::cout &lt;&lt; &quot;b b&quot; &lt;&lt; std::endl;
        };
        void printIt(Base&amp; b1, Base&amp; b2){
                b1.forwardIt(*this, b2);
        }
};

template&lt;typename T&gt;
class Forwardable{
public:
        virtual void forward(Foo&amp; f, Base&amp; base){
                f.print(base, dynamic_cast&lt;T&amp;&gt;(*this));
        }
        virtual void forward(Foo&amp; f, A&amp; a){
                f.print(a, dynamic_cast&lt;T&amp;&gt;(*this));
        }
        virtual void forward(Foo&amp; f, B&amp; b){
                f.print(b, dynamic_cast&lt;T&amp;&gt;(*this));
        }
        virtual void forwardIt(Foo&amp; f, Base&amp; base){
                base.forward(f, dynamic_cast&lt;Base&amp;&gt;(*this)); // EDIT2: hier sollte natürlich forward hin
        }
};

class A : public Base, public Forwardable&lt;A&gt;{};
class B : public Base, public Forwardable&lt;B&gt;{};
class C : public Base, public Forwardable&lt;Base&gt;{};

int main(){
        Foo f;
        A a;
        B b;
        C c;
        std::vector&lt;Base*&gt; vec;
        vec.push_back(&amp;a);
        vec.push_back(&amp;b);
        vec.push_back(&amp;c);
        for(std::vector&lt;Base*&gt;::const_iterator it = vec.begin(); it!=vec.end(); ++it){ EDIT3: kein Kommentar
                for(std::vector&lt;Base*&gt;::const_iterator it2 = vec.begin(); it2!=vec.end(); ++it2){
                        f.printIt(**it, **it2);
                }
        }
        return 0;
}
</code></pre>
<p>EDIT: Ehrlich gesagt versteh ich im Moment nicht, warum er mir unimplementierte<br />
Funktionen anmeckert...<br />
Generell hätte ich auch gesagt, dass ein static_cast ausreicht <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f921.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--clown_face"
      title=":clown:"
      alt="🤡"
    /></p>
<p>Gruß,<br />
CSpille</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923783</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923783</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 09 Jul 2010 10:33:08 GMT</pubDate></item><item><title><![CDATA[Reply to Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll on Fri, 09 Jul 2010 10:24:11 GMT]]></title><description><![CDATA[<p>Habe übersehen, dass die Argumente verschieden sind. Klar gehts um double dispatch. Wenn man keinen dynamic_cast will, scheint mir die Lösung von SeppJ noch die eleganteste.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923791</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923791</guid><dc:creator><![CDATA[Humbert]]></dc:creator><pubDate>Fri, 09 Jul 2010 10:24:11 GMT</pubDate></item><item><title><![CDATA[Reply to Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll on Fri, 09 Jul 2010 10:36:22 GMT]]></title><description><![CDATA[<p>Humbert schrieb:</p>
<blockquote>
<p>Habe übersehen, dass die Argumente verschieden sind. Klar gehts um double dispatch. Wenn man keinen dynamic_cast will, scheint mir die Lösung von SeppJ noch die eleganteste.</p>
</blockquote>
<p>häh...</p>
<p>Hab ich was verpaßt?<br />
Klar mußt du in jeder Funktion casten. Du kriegst ja nur ein Base&amp; als Parameter</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923803</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923803</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 09 Jul 2010 10:36:22 GMT</pubDate></item><item><title><![CDATA[Reply to Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll on Fri, 09 Jul 2010 10:48:40 GMT]]></title><description><![CDATA[<p>Hab ich auch was verpasst?<br />
Ich dachte meine Version ist genau so, wie man Double Dispatch in C++ implementiert!?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923812</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923812</guid><dc:creator><![CDATA[Jockelx]]></dc:creator><pubDate>Fri, 09 Jul 2010 10:48:40 GMT</pubDate></item><item><title><![CDATA[Reply to Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll on Fri, 09 Jul 2010 12:12:49 GMT]]></title><description><![CDATA[<p>Ganz viele Leute schrieb:</p>
<blockquote>
<p>double dispatch</p>
</blockquote>
<p>Jaaa, das ist es was ich suchte. Danke an alle Helfer! <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="👍"
    /> Ahnte ich doch, dass es dafür eine Standardlösung geben muss.</p>
<p>Ich sollte mir wohl mal ein Buch über solche Techniken durchlesen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923863</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923863</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Fri, 09 Jul 2010 12:12:49 GMT</pubDate></item><item><title><![CDATA[Reply to Über Basisklassenzeiger entscheiden welche spezialisierte Funktion aufgerufen werden soll on Fri, 09 Jul 2010 13:01:39 GMT]]></title><description><![CDATA[<p>SeppJ schrieb:</p>
<blockquote>
<p>Ahnte ich doch, dass es dafür eine Standardlösung geben muss.</p>
</blockquote>
<p>Gibts nicht. Es gibt viele verschiedene Ansätze die diesen Mangel in C++ (kein double Dispatch in der Sprache eingebaut) angehen, aber alle haben ihre Vor- und Nachteile. Und keiner ist eine &quot;Standardlösung&quot;</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1923896</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1923896</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Fri, 09 Jul 2010 13:01:39 GMT</pubDate></item></channel></rss>