<?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[Singleton &amp;quot;Base class&amp;quot;. Welches Design?]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich möchte mehrere Klassen zu Singletons machen und jetzt frage ich mich, welches Design am schönsten ist und am wenigsten Probleme macht.<br />
Mir schweben folgende 2 Ideen vor:</p>
<pre><code class="language-cpp">template &lt;typename C&gt;
 class Singleton
 {
 public:
    static C* instance ()
    {
       if (!_instance)
          _instance = new C ();
       return _instance;
    }
    virtual
    ~Singleton ()
    {
       _instance = 0;
    }
 private:
    static C* _instance;
protected:
    Singleton () { }
 };
 template &lt;typename C&gt; C* Singleton &lt;C&gt;::_instance = 0;

/* Verwendung */
 class Test : public Singleton &lt;Test&gt;
 {
 friend class Singleton &lt;Test&gt;;
 public:
    ~Test () { };
    static Test* instance ()
    {
       return Singleton &lt;Test&gt;::instance ();
    }
    void xyz () { }
 protected:
    Test () : Singleton &lt;Test&gt; () { }
 };
 Test::instance ()-&gt;xyz ();
</code></pre>
<p>Wenn ich nun eine Klasse T zum Singleton machen will, muss ich folgendes machen: von Singleton&lt;T&gt; ableiten, friend class Singleton&lt;T&gt; einfügen und alle Ctor + operator= private machen.</p>
<p>2. Variante:</p>
<pre><code class="language-cpp">Makro (Stack)
 #define DEF_SINGLETON( NAME )    \
 public:                        \
    static NAME&amp; instance()      \
    {                            \
       static NAME _instance;    \
       return _instance;         \
    }                            \
 private:                       \
    NAME();               \
    NAME( const NAME&amp; );

 /* Verwendung */
 class N
 {
    DEF_SINGLETON( N )
 public:
    void xyz();
 };
 ...
 N&amp; s = N::instance();
 s.xyz();
</code></pre>
<p>Obwohl ich Makros nicht mag, find ich diese Idee irgendwie ziemlich clever. ich brauch nur das eine kleine Makro in die Klassendeklaration schreiben und bin fertig.<br />
Welches Design würdet ihr wählen? Oder ein ganz anderes?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/246773/singleton-quot-base-class-quot-welches-design</link><generator>RSS for Node</generator><lastBuildDate>Thu, 17 Sep 2026 21:25:33 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/246773.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 01 Aug 2009 14:22:20 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 14:22:20 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich möchte mehrere Klassen zu Singletons machen und jetzt frage ich mich, welches Design am schönsten ist und am wenigsten Probleme macht.<br />
Mir schweben folgende 2 Ideen vor:</p>
<pre><code class="language-cpp">template &lt;typename C&gt;
 class Singleton
 {
 public:
    static C* instance ()
    {
       if (!_instance)
          _instance = new C ();
       return _instance;
    }
    virtual
    ~Singleton ()
    {
       _instance = 0;
    }
 private:
    static C* _instance;
protected:
    Singleton () { }
 };
 template &lt;typename C&gt; C* Singleton &lt;C&gt;::_instance = 0;

/* Verwendung */
 class Test : public Singleton &lt;Test&gt;
 {
 friend class Singleton &lt;Test&gt;;
 public:
    ~Test () { };
    static Test* instance ()
    {
       return Singleton &lt;Test&gt;::instance ();
    }
    void xyz () { }
 protected:
    Test () : Singleton &lt;Test&gt; () { }
 };
 Test::instance ()-&gt;xyz ();
</code></pre>
<p>Wenn ich nun eine Klasse T zum Singleton machen will, muss ich folgendes machen: von Singleton&lt;T&gt; ableiten, friend class Singleton&lt;T&gt; einfügen und alle Ctor + operator= private machen.</p>
<p>2. Variante:</p>
<pre><code class="language-cpp">Makro (Stack)
 #define DEF_SINGLETON( NAME )    \
 public:                        \
    static NAME&amp; instance()      \
    {                            \
       static NAME _instance;    \
       return _instance;         \
    }                            \
 private:                       \
    NAME();               \
    NAME( const NAME&amp; );

 /* Verwendung */
 class N
 {
    DEF_SINGLETON( N )
 public:
    void xyz();
 };
 ...
 N&amp; s = N::instance();
 s.xyz();
</code></pre>
<p>Obwohl ich Makros nicht mag, find ich diese Idee irgendwie ziemlich clever. ich brauch nur das eine kleine Makro in die Klassendeklaration schreiben und bin fertig.<br />
Welches Design würdet ihr wählen? Oder ein ganz anderes?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753533</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753533</guid><dc:creator><![CDATA[wolke_]]></dc:creator><pubDate>Sat, 01 Aug 2009 14:22:20 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 14:30:06 GMT]]></title><description><![CDATA[<p>Was haben in letzter Zeit alle mit Singletons?! <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
<p>Naja. Mir gefällt das Meyers Singleton einfach am besten. Das ist im wesentlichen eigentlich deine zweite Variante, aber ohne Makros, sondern mit einer Basisklasse. Und ob du jetzt</p>
<pre><code class="language-cpp">DEF_SINGLETON( N )
</code></pre>
<p>oder</p>
<pre><code class="language-cpp">class n : public singleton&lt; n &gt; {}
</code></pre>
<p>spielt (von der Schreibarbeit) ja keine Rolle mehr. (oder es halt in jeder Klasse definieren, aber das ist ja eine andere Diskussion).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753539</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753539</guid><dc:creator><![CDATA[drakon]]></dc:creator><pubDate>Sat, 01 Aug 2009 14:30:06 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 14:39:20 GMT]]></title><description><![CDATA[<p>Naja, aber wenn ich ableite, dann muss ich doch explit noch alle Ctor's und operator= private machen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753546</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753546</guid><dc:creator><![CDATA[wolke_]]></dc:creator><pubDate>Sat, 01 Aug 2009 14:39:20 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 15:10:10 GMT]]></title><description><![CDATA[<p>wolke_ schrieb:</p>
<blockquote>
<p>Naja, aber wenn ich ableite, dann muss ich doch explit noch alle Ctor's und operator= private machen?</p>
</blockquote>
<p>Diese 4 Zeilen hast du wohl in null Komma nichts geschrieben. Also nur deswegen auf auf ein Makro setzen, würde ich nicht. Zudem hat man so auch die Möglichkeit zu wählen, ob man sie <code>private</code> oder <code>protected</code> machen möchte. Vielleicht möchte man sie sogar <code>public</code> machen, habe ich auch schon gesehen.</p>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753570</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753570</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Sat, 01 Aug 2009 15:10:10 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 15:16:56 GMT]]></title><description><![CDATA[<p>Also ich habe mir jetzt gerade mal eine Singleton Klasse selber geschrieben. Das wichtige: Meine Singleton Klasse braucht Parameter im Constructor. Das übliche</p>
<pre><code class="language-cpp">getInstance() { static LoggerTest log; return log;}
</code></pre>
<p>geht bei mir also nicht.</p>
<p>Meine Klasse sieht so aus:</p>
<pre><code class="language-cpp">#include &lt;cassert&gt;
#include &lt;string&gt;
#include &lt;windows.h&gt;

class LoggerTest {
public:
	static void create(const std::string&amp; filename, int level) {
		if(instance == NULL) {
			instance = new LoggerTest();
			instance-&gt;createImpl(filename, level);
		}
	}

	static LoggerTest* getInstance() {
		assert(instance);
		return instance;
	}

	static void destroy() {
		if(instance) {
			OutputDebugStr(&quot;close file\n&quot;);
			delete instance;
			instance = NULL;
		}
	}

	// Methods
	void message() { OutputDebugStr(&quot;message\n&quot;); }

private:
	LoggerTest() { }
	LoggerTest(const LoggerTest&amp; rhs);
	LoggerTest&amp; operator=(const LoggerTest&amp; rhs);

	static LoggerTest* instance;

	void createImpl(const std::string&amp; filename, int level) { 
		OutputDebugStr(&quot;open file\n&quot;);
	}
};

// In Logger.cpp:
LoggerTest* LoggerTest::instance = NULL;
</code></pre>
<p>Die Ideen meiner Klasse: Die Klasse hat Methoden createImpl() und destroy(). createImpl() öffnet die Dateien usw. destroy() schließt die Dateien. Man benutzt meine Klasse in dem man EINMAL create(foo, bar) aufruft und dann nur noch getInstance(). Jetzt habe ich die Klasse mal getestet:</p>
<pre><code class="language-cpp">LoggerTest::create(&quot;&quot;, 2);       // ruft createImpl() auf, öffnet Dateien
LoggerTest* log = LoggerTest::getInstance();

log-&gt;message();                 // schreibt nachricht
LoggerTest::getInstance()-&gt;message();  // dito

LoggerTest::destroy();          // schließt dateien. delete instance

log-&gt;message();                 // dieser aufruft funktoniert! Wieso?
LoggerTest::getInstance()-&gt;message();
</code></pre>
<p>// Das hier gibt ein assert<br />
Im Grunde steht meine Frage schon im vorletzten Kommentar. Nachdem ich destroy() aufgerufen hab, klappt log-message() dennoch! Das versteh ich nicht. Nach destroy müsste doch log auf gelöschten Speicher zeigen und dann bei log-&gt;message() einen Fehler bringen. Wieso gibt das keinen Fehler? <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=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753576</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753576</guid><dc:creator><![CDATA[wolke_]]></dc:creator><pubDate>Sat, 01 Aug 2009 15:16:56 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 15:20:54 GMT]]></title><description><![CDATA[<p>Du rufst eine Funktion auf, die den this-Zeiger nicht braucht. Somit wird da da gar nie auf den 0-Zeiger zugegriffen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753580</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753580</guid><dc:creator><![CDATA[drakon]]></dc:creator><pubDate>Sat, 01 Aug 2009 15:20:54 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 15:21:29 GMT]]></title><description><![CDATA[<p>wolke_ schrieb:</p>
<blockquote>
<p>Wieso gibt das keinen Fehler?</p>
</blockquote>
<p>Weil es undefiniertes Verhalten ist. Es wäre i.O. wenn die Welt explodiert oder deine Festplatte gelöscht wird. Es ist nicht definiert, was dann passiert, bzw. der Standard sagt eben dazu: <em>undefined behavior</em>.<br />
Dies erlaubt den Kompilern unnötige Prüfungen wegzulassen, wodurch das Programm besser optimiert werden kann. Natürlich liegt dann mehr Verantwortung beim Programmierer.</p>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753581</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753581</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Sat, 01 Aug 2009 15:21:29 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 15:23:28 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">static void create(const std::string&amp; filename, int level) { 
        if(instance == NULL) { 
            instance = new LoggerTest(); 
            instance-&gt;createImpl(filename, level); 
        } 
    }
</code></pre>
<p>halte ich nicht für die allerbeste möglichkeit...</p>
<p>ich würde das get_instance() anders implementieren und der programmierer müsste dann halt noch die init-fkt (createImpl) selbst aufrufen - aber ist wohl geschmackssache...</p>
<p>bb</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753584</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753584</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sat, 01 Aug 2009 15:23:28 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 15:25:59 GMT]]></title><description><![CDATA[<p>drakon schrieb:</p>
<blockquote>
<p>Du rufst eine Funktion auf, die den this-Zeiger nicht braucht. Somit wird da da gar nie auf den 0-Zeiger zugegriffen.</p>
</blockquote>
<p>Versteh ich nicht. 1. braucht message() einen this Zeiger und 2. zeigt log auf Müll.</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/9752">@Dravere</a>: Verstehe. Es ist also im Grunde ein Fehler. Wie könnte ich meinen Code denn ein bißchen umschreiben, dass er funktioniert bzw besser ist?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753586</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753586</guid><dc:creator><![CDATA[wolke_]]></dc:creator><pubDate>Sat, 01 Aug 2009 15:25:59 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 15:40:19 GMT]]></title><description><![CDATA[<p>wolke_ schrieb:</p>
<blockquote>
<p>drakon schrieb:</p>
<blockquote>
<p>Du rufst eine Funktion auf, die den this-Zeiger nicht braucht. Somit wird da da gar nie auf den 0-Zeiger zugegriffen.</p>
</blockquote>
<p>Versteh ich nicht. 1. braucht message() einen this Zeiger und 2. zeigt log auf Müll.</p>
</blockquote>
<p>Das es undefiniert ist habe ich vergessen zu sagen, aber üblicherweise funktioniert das eben, weil kein this Zeiger gebraucht wird. Ich nehme mal nicht an, dass OutputDebugStr eine Member der Klasse ist und daher wird der this Zeiger eben nicht gebraucht..</p>
<p>Schlussentlich ist ja auch der <code>-&gt; - Operator</code> lediglich das hier:</p>
<pre><code class="language-cpp">operator -&gt; ( log );
</code></pre>
<p>Und wenn du jetzt innerhalb der Funktion log nicht benutzt, dann passiert auch nichts. (kann aber trotzdem einen Fehler geben, da undefiniert).</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/9752">@Dravere</a>: Verstehe. Es ist also im Grunde ein Fehler. Wie könnte ich meinen Code denn ein bißchen umschreiben, dass er funktioniert bzw besser ist?</p>
</blockquote>
<p>Fass den Zeiger nachdem du ihn auf 0 gesetzt hast einfach nicht mehr an..</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753597</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753597</guid><dc:creator><![CDATA[drakon]]></dc:creator><pubDate>Sat, 01 Aug 2009 15:40:19 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 15:56:06 GMT]]></title><description><![CDATA[<p>drakon schrieb:</p>
<blockquote>
<p>wolke_ schrieb:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/9752">@Dravere</a>: Verstehe. Es ist also im Grunde ein Fehler. Wie könnte ich meinen Code denn ein bißchen umschreiben, dass er funktioniert bzw besser ist?</p>
</blockquote>
<p>Fass den Zeiger nachdem du ihn auf 0 gesetzt hast einfach nicht mehr an..</p>
</blockquote>
<p>Das ist die übliche Methode und wird auch meistens so gemacht. Allerdings gäbe es auch eine Möglichkeit über <em>SmartPtr</em> etwas zu machen. Du könntest zum Beispiel einen <code>shared_ptr</code> speichern und auch zurückgeben. Wenn du <code>destroy</code> aufrufst, gibst du den <code>shared_ptr</code> im Singleton frei, der Speicher wird aber erst freigegeben, wenn der letzte Benutzer ihn nicht mehr verwendet.<br />
Du kannst aber auch eine eigene <em>SmartPtr</em>-Klasse implementieren, welche immer prüft, ob der Zeiger noch gültig ist und wenn nicht, beim Zugriff darauf eine Exception wirft.<br />
Ein ganz einfaches Beispiel:</p>
<pre><code class="language-cpp">class LoggerTestInstance
{
public:
  LoggerTest* operator -&gt;()
  {
    LoggerTest* instance = LoggerTest::getInstance();

    if(!instance)
    {
      throw Fehler();
    }

    return instance;
  }
};

// Verwendung:
LoggerTestInstance loggerTest;
loggerTest-&gt;message();
</code></pre>
<p>Kann man beliebig erweitern und verbessern <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>
<p>Es gibt viele weitere komplexe Wege, aber am einfachsten ist es, nach <code>destroy</code> nicht mehr anfassen <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>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753611</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753611</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Sat, 01 Aug 2009 15:56:06 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 16:12:49 GMT]]></title><description><![CDATA[<p>Danke für die Tipps!</p>
<p>Dravere schrieb:</p>
<blockquote>
<p>Es gibt viele weitere komplexe Wege, aber am einfachsten ist es, nach <code>destroy</code> nicht mehr anfassen <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>
</blockquote>
<p>Ja, genau so werde ich es auch machen. Mit shared_ptr usw. find ich schon wieder mit Kanonen auf Spatzen schießen. Am Ende krieg ich sonst noch total &quot;overdesigned&quot; Code wie in boost und komme zu nix mehr <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="😉"
    /> Der Benutzer darf den Logger nach destroy() einfach nicht mehr benutzen und fertig.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753623</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753623</guid><dc:creator><![CDATA[wolke_]]></dc:creator><pubDate>Sat, 01 Aug 2009 16:12:49 GMT</pubDate></item><item><title><![CDATA[Reply to Singleton &amp;quot;Base class&amp;quot;. Welches Design? on Sat, 01 Aug 2009 17:19:07 GMT]]></title><description><![CDATA[<p>Singletons are evil.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1753647</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1753647</guid><dc:creator><![CDATA[Opinion.]]></dc:creator><pubDate>Sat, 01 Aug 2009 17:19:07 GMT</pubDate></item></channel></rss>