<?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[Designfrage bzgl. Klassenhierarchie]]></title><description><![CDATA[<p>Hiho,</p>
<p>Ich habe in meinem Programm eine Klassenhierarchie, die sich vor allem eher lange ist (~15 Schichten) aber nicht sonderlich breit (1-3 abgeleitete Klassen pro Klasse). Die Klasseneinteilung an sich macht m.E.n. Sinn; jede Klasse fügt neue Member und Funktionen hinzu und das Verhalten der virtuellen Methoden ist auch sinnvoll.<br />
Meine Frage nun:<br />
Ich habe nun z.B. ganz zu oberst in der Hierarchie eine abstrakte Klasse, die eine virtuelle Funktion <code>Refresh</code> anbietet. Der Sinn dieser Methode ist es, gewisse Caches und Puffer zu aktualisieren und bestimmte Berechnungen neu durchzuführen. In meiner Hierarchie gibt es sowohl Klassen, die nichts zu machen haben im Falle eines <code>Refresh</code> s, als auch jene, die einen bestimmten Code ausführen müssen. Das Problem ist jedoch, dass der alte Code von <code>Refresh</code> überschrieben würde, wenn ich einfach die Methode implementiere tiefer in der Hierarchie.</p>
<p>Mögliche Lösung:</p>
<pre><code>class Base {
public:
	virtual ~Base() = default;
	virutal void Refresh() {}
};
class Foo : public Base {
protected:
	void RefreshFoo() {/*...*/}
public:
	virtual void Refresh() override
	{
		RefreshFoo();
	}
};
class Bar : public Base {
protected:
	void RefreshBar()
	{
		RefreshFoo();
		// ...
	}
public:
	virtual void Refresh() override
	{
		RefreshBar();
	}
};
class Qux : public Base {
protected:
	void RefreshQux()
	{
		RefreshBar();
		// ...
	}
public:
	virtual void Refresh() override
	{
		RefreshQux();
	}
};
</code></pre>
<p>Das ist meine aktuelle Lösung. Zu den Probleme zählen, dass ich oft <code>Base&lt;...&gt;::</code> schreiben muss, dass es sehr redundant ist und dass es mühsam zu ändern ist.</p>
<p>Mir ist da auch noch in den Sinn gekommen, dass man <code>Refresh</code> non- <code>virutal</code> machen und dann in der Basisklasse einen Vektor mit Listener machen könnte. Dann würde jeder Konstruktor bedingt seine Methoden hinzufügen. Was mir daran gar nicht gefällt, ist, dass da dynamischer Speicher verwendet wird. Vor allem weil die Anzahl der Listener beim Instantiieren feststünde. Außerdem vermute ich stark, dass die Performance da nicht ungeschoren davonkommt...</p>
<p>Kennt da jemand eine Lösung zu diesem Problem? Ist das ein wohlbekanntes Problem?</p>
<p>LG</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/340302/designfrage-bzgl-klassenhierarchie</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Apr 2026 08:36:02 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/340302.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 30 Oct 2016 16:49:24 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Designfrage bzgl. Klassenhierarchie on Sun, 30 Oct 2016 16:49:24 GMT]]></title><description><![CDATA[<p>Hiho,</p>
<p>Ich habe in meinem Programm eine Klassenhierarchie, die sich vor allem eher lange ist (~15 Schichten) aber nicht sonderlich breit (1-3 abgeleitete Klassen pro Klasse). Die Klasseneinteilung an sich macht m.E.n. Sinn; jede Klasse fügt neue Member und Funktionen hinzu und das Verhalten der virtuellen Methoden ist auch sinnvoll.<br />
Meine Frage nun:<br />
Ich habe nun z.B. ganz zu oberst in der Hierarchie eine abstrakte Klasse, die eine virtuelle Funktion <code>Refresh</code> anbietet. Der Sinn dieser Methode ist es, gewisse Caches und Puffer zu aktualisieren und bestimmte Berechnungen neu durchzuführen. In meiner Hierarchie gibt es sowohl Klassen, die nichts zu machen haben im Falle eines <code>Refresh</code> s, als auch jene, die einen bestimmten Code ausführen müssen. Das Problem ist jedoch, dass der alte Code von <code>Refresh</code> überschrieben würde, wenn ich einfach die Methode implementiere tiefer in der Hierarchie.</p>
<p>Mögliche Lösung:</p>
<pre><code>class Base {
public:
	virtual ~Base() = default;
	virutal void Refresh() {}
};
class Foo : public Base {
protected:
	void RefreshFoo() {/*...*/}
public:
	virtual void Refresh() override
	{
		RefreshFoo();
	}
};
class Bar : public Base {
protected:
	void RefreshBar()
	{
		RefreshFoo();
		// ...
	}
public:
	virtual void Refresh() override
	{
		RefreshBar();
	}
};
class Qux : public Base {
protected:
	void RefreshQux()
	{
		RefreshBar();
		// ...
	}
public:
	virtual void Refresh() override
	{
		RefreshQux();
	}
};
</code></pre>
<p>Das ist meine aktuelle Lösung. Zu den Probleme zählen, dass ich oft <code>Base&lt;...&gt;::</code> schreiben muss, dass es sehr redundant ist und dass es mühsam zu ändern ist.</p>
<p>Mir ist da auch noch in den Sinn gekommen, dass man <code>Refresh</code> non- <code>virutal</code> machen und dann in der Basisklasse einen Vektor mit Listener machen könnte. Dann würde jeder Konstruktor bedingt seine Methoden hinzufügen. Was mir daran gar nicht gefällt, ist, dass da dynamischer Speicher verwendet wird. Vor allem weil die Anzahl der Listener beim Instantiieren feststünde. Außerdem vermute ich stark, dass die Performance da nicht ungeschoren davonkommt...</p>
<p>Kennt da jemand eine Lösung zu diesem Problem? Ist das ein wohlbekanntes Problem?</p>
<p>LG</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2513486</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2513486</guid><dc:creator><![CDATA[gezly]]></dc:creator><pubDate>Sun, 30 Oct 2016 16:49:24 GMT</pubDate></item><item><title><![CDATA[Reply to Designfrage bzgl. Klassenhierarchie on Sun, 30 Oct 2016 18:31:25 GMT]]></title><description><![CDATA[<p>Ich weiß nicht, ob ich dein Problem verstehe. Ist das vielleicht eine Lösung?</p>
<pre><code>struct b {
  virtual void doit(){}
};

struct d : b{
  void doit() { // do something
     b::doit();
     // do an other thing
  }
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2513509</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2513509</guid><dc:creator><![CDATA[manni66]]></dc:creator><pubDate>Sun, 30 Oct 2016 18:31:25 GMT</pubDate></item><item><title><![CDATA[Reply to Designfrage bzgl. Klassenhierarchie on Sun, 30 Oct 2016 18:44:51 GMT]]></title><description><![CDATA[<p>Nein, weil <code>std::unique_ptr&lt;b&gt;{std::make_unique&lt;d&gt;()}-&gt;doit();</code> nur den <code>b</code> -spezifischen Code aufruft.<br />
Ich will, dass ich die Methode von der Basisklasse aus aufrufen kann und dass dann alle abgeleiteten &quot;Schichten&quot; ihren zusätzlichen Code ausführen. Beispielsweise:</p>
<pre><code>std::unique_ptr&lt;Base&gt;{std::make_unique&lt;Foo&gt;()}-&gt;Refresh(); // soll die Daten von Base und Foo refreshen
std::unique_ptr&lt;Base&gt;{std::make_unique&lt;Bar&gt;()}-&gt;Refresh(); // soll die Daten von Base, Foo und Bar refreshen
std::unique_ptr&lt;Base&gt;{std::make_unique&lt;Qux&gt;()}-&gt;Refresh(); // soll die Daten von Base, Foo, Bar und Qux refreshen
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2513512</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2513512</guid><dc:creator><![CDATA[gezly]]></dc:creator><pubDate>Sun, 30 Oct 2016 18:44:51 GMT</pubDate></item><item><title><![CDATA[Reply to Designfrage bzgl. Klassenhierarchie on Sun, 30 Oct 2016 18:54:12 GMT]]></title><description><![CDATA[<p>gezly schrieb:</p>
<blockquote>
<p>Nein, weil <code>std::unique_ptr&lt;b&gt;{std::make_unique&lt;d&gt;()}-&gt;doit();</code> nur den <code>b</code> -spezifischen Code aufruft</p>
</blockquote>
<p>Nein, warum sollte es?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2513513</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2513513</guid><dc:creator><![CDATA[manni66]]></dc:creator><pubDate>Sun, 30 Oct 2016 18:54:12 GMT</pubDate></item><item><title><![CDATA[Reply to Designfrage bzgl. Klassenhierarchie on Sun, 30 Oct 2016 19:09:50 GMT]]></title><description><![CDATA[<p>manni66 schrieb:</p>
<blockquote>
<p>Nein, warum sollte es?</p>
</blockquote>
<p>Ach, das wird auch dynamisch gebunden, obwohl kein <code>virtual</code> vor der Definition von <code>doit</code> in <code>d</code> da steht? Ist mir neu, sorry. Ich mach schon aus Routine überall <code>virtual</code> und <code>override</code> dran.</p>
<p>Ja, das löst es. Das ist dann prinzipiell dasselbe wie mein Code im OP nur mit weniger Boilerplate aber mit den noch immer selben Probleme:<br />
- jedes mal die Basisklasse angeben zu müssen, insb. wenn Template-Argumente involviert sind<br />
- sehr mühsam zu ändern, wenn es Änderungen in der Klassenhierarchie gibt<br />
- keine Checks, falls ich den Basisklassen-Aufruf irgendwo vergesse</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2513515</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2513515</guid><dc:creator><![CDATA[gezly]]></dc:creator><pubDate>Sun, 30 Oct 2016 19:09:50 GMT</pubDate></item><item><title><![CDATA[Reply to Designfrage bzgl. Klassenhierarchie on Sun, 30 Oct 2016 23:06:56 GMT]]></title><description><![CDATA[<p>gezly schrieb:</p>
<blockquote>
<p>- jedes mal die Basisklasse angeben zu müssen, insb. wenn Template-Argumente involviert sind<br />
- sehr mühsam zu ändern, wenn es Änderungen in der Klassenhierarchie gibt<br />
- keine Checks, falls ich den Basisklassen-Aufruf irgendwo vergesse</p>
</blockquote>
<p>- naja, nur wenn die Funktion in einer Klasse auch implementiert wird. Das ist ja so wie du sagst nicht immer der Fall<br />
- wenn du die Schnittstelle dauernd änderst, ist die Klassenhierarchie vielleicht dein geringstes Problem<br />
- dann wirst du wohl dran denken und gut testen müssen</p>
<p>Die 15 Ebenen sind doch schon nicht ganz einfach...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2513554</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2513554</guid><dc:creator><![CDATA[manni66]]></dc:creator><pubDate>Sun, 30 Oct 2016 23:06:56 GMT</pubDate></item></channel></rss>