<?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[Abstrakte Klasse in std::map]]></title><description><![CDATA[<p>Hey,<br />
ich bastel hier gerade an einem kleinen Spielchen und habe mir folgende (abstrakte) Basisklasse für alle Spielobjekte gebaut:</p>
<pre><code class="language-cpp">#ifndef __JEIX_OBJ_BASE_HPP__
#define __JEIX_OBJ_BASE_HPP__

#include &lt;map&gt;
#include &lt;SFML/Graphics.hpp&gt;
#include &quot;manager.hpp&quot;

// forwad declaration
class Manager;

class GameObject
{
	Manager&amp;   _manager;
	sf::Sprite _sprite;

public:
	GameObject(Manager&amp; manager) : _manager(manager) {}
	virtual void think() = 0;
	virtual sf::Sprite&amp; getSprite() { return _sprite; }
};

#endif
</code></pre>
<p>Ich hatte mir nämlich gedacht, dass ich davon die einzelnen Charaktere ableiten könnte, um die dann in eine <code>std::map&lt;std::string, GameObject&gt;</code> oder so zu packen. Aber das geht wohl so direkt nicht, denn bei folgender Konstellation: <code>std::map&lt;std::string, GameObject&gt;</code> ; gibt er mir einen Fehler, dass man keine Instanz von einer abstrakten Klasse erstellen könne. Nun gut, dass man eine abstrakte Klasse nicht instanzieren kann, ist mir bewusst, aber wieso er bei der Variablendeklaration versucht, davon schon eine Instanz zu erstellen ist mir schleierhaft :[.</p>
<p>Nun zu meiner eigentlich Frage, wie würdet ihr das lösen? Zwei Ansätze, die mir da grad spotan einfallen wären, einfach die Map so zu definieren: <code>std::map&lt;std::string, GameObject*&gt;</code> und mit Pointern arbeiten, was mir aber eigentlich weniger gefällt -&gt; Pointer. Und der andere wäre eine kleine Wrapper Klasse zu erstellen alâ GameObjectHandle, die einen GameObject Zeiger enthält. Siehe hier: <a href="http://www.gamedev.net/community/forums/viewreply.asp?ID=2630441" rel="nofollow">http://www.gamedev.net/community/forums/viewreply.asp?ID=2630441</a> der Post von Zahlman</p>
<p>Zum Schluss könnte man auch einfach die Klasse nicht abstrakt machen, dagegen spricht jedoch, dass man sie eigentlich nicht zum instanzieren gedacht ist und nur die Schnittstelle think() definiert, die jedes Objekt haben sollte. Wie würdet ihr das lösen? btw: sonstige Anmerkungen zum Code werden auch gern angenommen. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/topic/240721/abstrakte-klasse-in-std-map</link><generator>RSS for Node</generator><lastBuildDate>Mon, 21 Sep 2026 20:53:46 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/240721.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 10 May 2009 19:08:10 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Abstrakte Klasse in std::map on Sun, 10 May 2009 19:16:24 GMT]]></title><description><![CDATA[<p>Hey,<br />
ich bastel hier gerade an einem kleinen Spielchen und habe mir folgende (abstrakte) Basisklasse für alle Spielobjekte gebaut:</p>
<pre><code class="language-cpp">#ifndef __JEIX_OBJ_BASE_HPP__
#define __JEIX_OBJ_BASE_HPP__

#include &lt;map&gt;
#include &lt;SFML/Graphics.hpp&gt;
#include &quot;manager.hpp&quot;

// forwad declaration
class Manager;

class GameObject
{
	Manager&amp;   _manager;
	sf::Sprite _sprite;

public:
	GameObject(Manager&amp; manager) : _manager(manager) {}
	virtual void think() = 0;
	virtual sf::Sprite&amp; getSprite() { return _sprite; }
};

#endif
</code></pre>
<p>Ich hatte mir nämlich gedacht, dass ich davon die einzelnen Charaktere ableiten könnte, um die dann in eine <code>std::map&lt;std::string, GameObject&gt;</code> oder so zu packen. Aber das geht wohl so direkt nicht, denn bei folgender Konstellation: <code>std::map&lt;std::string, GameObject&gt;</code> ; gibt er mir einen Fehler, dass man keine Instanz von einer abstrakten Klasse erstellen könne. Nun gut, dass man eine abstrakte Klasse nicht instanzieren kann, ist mir bewusst, aber wieso er bei der Variablendeklaration versucht, davon schon eine Instanz zu erstellen ist mir schleierhaft :[.</p>
<p>Nun zu meiner eigentlich Frage, wie würdet ihr das lösen? Zwei Ansätze, die mir da grad spotan einfallen wären, einfach die Map so zu definieren: <code>std::map&lt;std::string, GameObject*&gt;</code> und mit Pointern arbeiten, was mir aber eigentlich weniger gefällt -&gt; Pointer. Und der andere wäre eine kleine Wrapper Klasse zu erstellen alâ GameObjectHandle, die einen GameObject Zeiger enthält. Siehe hier: <a href="http://www.gamedev.net/community/forums/viewreply.asp?ID=2630441" rel="nofollow">http://www.gamedev.net/community/forums/viewreply.asp?ID=2630441</a> der Post von Zahlman</p>
<p>Zum Schluss könnte man auch einfach die Klasse nicht abstrakt machen, dagegen spricht jedoch, dass man sie eigentlich nicht zum instanzieren gedacht ist und nur die Schnittstelle think() definiert, die jedes Objekt haben sollte. Wie würdet ihr das lösen? btw: sonstige Anmerkungen zum Code werden auch gern angenommen. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1708623</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1708623</guid><dc:creator><![CDATA[issen1]]></dc:creator><pubDate>Sun, 10 May 2009 19:16:24 GMT</pubDate></item><item><title><![CDATA[Reply to Abstrakte Klasse in std::map on Sun, 10 May 2009 19:21:06 GMT]]></title><description><![CDATA[<blockquote>
<p>Nun zu meiner eigentlich Frage, wie würdet ihr das lösen? Zwei Ansätze, die mir da grad spotan einfallen wären, einfach die Map so zu definieren: std::map&lt;std::string, GameObject*&gt; und mit Pointern arbeiten, was mir aber eigentlich weniger gefällt -&gt; Pointer.</p>
</blockquote>
<p>Nö, genau der Richtige Ansatz.Wenn dein GameObject eh als abstrakte Klassen dienen soll, musst du Pointer verwenden um die Laufzeitpolymorphie zu gewährleisten, was ja meistens der Sinn einer abstrakten Klasse ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1708637</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1708637</guid><dc:creator><![CDATA[Firefighter]]></dc:creator><pubDate>Sun, 10 May 2009 19:21:06 GMT</pubDate></item><item><title><![CDATA[Reply to Abstrakte Klasse in std::map on Sun, 10 May 2009 21:36:52 GMT]]></title><description><![CDATA[<p>Jetzt kommen meine Wissenslücken durch. Ich hab hier mal ein kleinen Beispiel-Code geschrieben, einmal mit eigenhändiger Speicherverwaltung und einmal mit den boost::shared_ptr-Pointern. Aber ich weiß nicht, ob da auch wirklich keine Speicherlecks enstehen, weil ich mir bei den STL-Containern nicht sicher war, wie ich da den Speicher freigeben kann, so dass der auch wirklich freigegeben ist und der Container auch nachher alles ordentlich aufräumt. Und bei Boost war ich mir nicht sicher, ob das so richtig angewendet ist. <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>
<p>Hier der Code:</p>
<pre><code class="language-cpp">#include&lt;iostream&gt;
#include&lt;string&gt;
#include&lt;map&gt;
#include&lt;boost/shared_ptr.hpp&gt;

/*
 *
 *   test.cpp
 *
 */

class Base
{
	int foo;
	float bar;

public:
	virtual ~Base() {}
	virtual void print() = 0;
};

class Drucker : public Base
{
public:
	void print() { std::cout &lt;&lt; &quot;Printed..&quot; &lt;&lt; std::endl; }
};

class Scanner : public Base
{
public:
	void print() { std::cout &lt;&lt; &quot;Scanned..&quot; &lt;&lt; std::endl; }
};

typedef std::map&lt;std::string, Base*&gt; List;
typedef boost::shared_ptr&lt;Base&gt; BasePtr;
typedef std::map&lt;std::string, BasePtr&gt; BList;

int main()
{
	/*
	 *   manuelle Speicherverwaltung:
	 */
	List list;
	list[&quot;drucker&quot;] = new Drucker();
	list[&quot;scanner&quot;] = new Scanner();

	List::iterator it;
	for(it=list.begin();it!=list.end();it++)
	{
		it-&gt;second-&gt;print();
		delete (it-&gt;second); // so okay?
	}
	list.clear();
	std::cout &lt;&lt; list.size() &lt;&lt; std::endl;

	/*
	 *   boost::shared_pointer
	 */
	BList blist;	
	blist[&quot;drucker&quot;] = BasePtr(new Drucker()); // ist das eigentlich erlaubt, wegen temporärem shared_pointer?
	blist[&quot;scanner&quot;] = BasePtr(new Scanner());

	BList::iterator bit;
	for(bit=blist.begin();bit!=blist.end();bit++)
	{
		bit-&gt;second-&gt;print();
	}
	blist.clear();
	std::cout &lt;&lt; blist.size();

	std::cin.ignore();
    return 0;
}
</code></pre>
<p>*Bitte nicht hauen, ich wollte lieber fragen, als später Speicherlecks zu haben*</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1708709</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1708709</guid><dc:creator><![CDATA[issen1]]></dc:creator><pubDate>Sun, 10 May 2009 21:36:52 GMT</pubDate></item><item><title><![CDATA[Reply to Abstrakte Klasse in std::map on Mon, 11 May 2009 05:21:46 GMT]]></title><description><![CDATA[<p>Also das hier:</p>
<pre><code class="language-cpp">BasePtr(new Drucker())
</code></pre>
<p>Ist nicht notwendig. Ein einfaches <code>new Drucker()</code> reicht da komplett aus.Ansonsten sieht der Rest ganz gut aus, bis auf deine Benennung natürlich, weil <code>List</code> lässt auf einen ganz anderen container schließen, als der der bei dir eigentlich dahinter liegt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1708751</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1708751</guid><dc:creator><![CDATA[Firefighter]]></dc:creator><pubDate>Mon, 11 May 2009 05:21:46 GMT</pubDate></item><item><title><![CDATA[Reply to Abstrakte Klasse in std::map on Mon, 11 May 2009 09:01:08 GMT]]></title><description><![CDATA[<p>Firefighter schrieb:</p>
<blockquote>
<p>Also das hier:</p>
<pre><code class="language-cpp">BasePtr(new Drucker())
</code></pre>
<p>Ist nicht notwendig.</p>
</blockquote>
<p>Doch, ist es. Die Konstruktoren von Boost.SharedPtr sind <code>explicit</code> . Der <code>operator =</code> nimmt nur ein Objekt gleichen Typs an, also keinen Zeiger. Eine implizite Umwandlung gibt es somit nicht und wollte man auch bewusst verhindern.</p>
<p>Lies vielleicht auch gleich mal dies (und zwar issen1, wie auch Firefighter):<br />
-&gt; <a href="http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm#BestPractices" rel="nofollow">http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm#BestPractices</a></p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/20610">@issen1</a>,<br />
Dies wäre vielleicht auch noch etwas praktisches für dich:<br />
<a href="http://www.boost.org/doc/libs/1_39_0/libs/ptr_container/doc/ptr_container.html" rel="nofollow">http://www.boost.org/doc/libs/1_39_0/libs/ptr_container/doc/ptr_container.html</a></p>
<p>Bzw. zum Beispiel die <code>ptr_map</code> :<br />
<a href="http://www.boost.org/doc/libs/1_39_0/libs/ptr_container/doc/ptr_map.html" rel="nofollow">http://www.boost.org/doc/libs/1_39_0/libs/ptr_container/doc/ptr_map.html</a></p>
<p>Dieser Container löscht deine Objekte automatisch per <code>delete</code> . Sowas ist deutlich effizienter als ein Boost.SharedPtr in einer STL Map.</p>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1708841</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1708841</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Mon, 11 May 2009 09:01:08 GMT</pubDate></item><item><title><![CDATA[Reply to Abstrakte Klasse in std::map on Mon, 11 May 2009 09:35:56 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">BList blist;   
blist[&quot;drucker&quot;] = BasePtr(new Drucker());
blist[&quot;scanner&quot;] = BasePtr(new Scanner());
</code></pre>
<p>(edit: hab das falsche mal entfernt)</p>
<p>Gut, auf jeden Fall danke, ich werde das mal umsetzen. Sollte ich dann lieber die Smart Pointer nutzen oder doch selber den Speicher verwalten? Und ja, List war unglücklich gewählt, ist aber ja auch nur ein Beispiel gewesen ;).</p>
<p>Edit auf Dravere: Deswegen hatte ich es auch erst so gemacht und ich werde mir die ptr_map mal anschauen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1708843</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1708843</guid><dc:creator><![CDATA[issen1]]></dc:creator><pubDate>Mon, 11 May 2009 09:35:56 GMT</pubDate></item><item><title><![CDATA[Reply to Abstrakte Klasse in std::map on Mon, 11 May 2009 09:18:06 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/9752">@dravere</a>, danke dir. Den explizit ctor hatte ich ganz vergessen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1708855</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1708855</guid><dc:creator><![CDATA[Firefighter]]></dc:creator><pubDate>Mon, 11 May 2009 09:18:06 GMT</pubDate></item><item><title><![CDATA[Reply to Abstrakte Klasse in std::map on Mon, 11 May 2009 09:53:28 GMT]]></title><description><![CDATA[<p>issen1 schrieb:</p>
<blockquote>
<p>...<br />
Sollte ich dann lieber die Smart Pointer nutzen oder doch selber den Speicher verwalten?</p>
</blockquote>
<p>Wenn du die Daten nur und ausschließlich an einer Stelle verwaltest, würde ich zu den ptr-Containern raten. Wenn du die Daten aber verteilst, und der letzte &quot;das Licht ausmachen soll&quot;, sind shared_ptr die bessere Wahl.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1708871</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1708871</guid><dc:creator><![CDATA[asc]]></dc:creator><pubDate>Mon, 11 May 2009 09:53:28 GMT</pubDate></item><item><title><![CDATA[Reply to Abstrakte Klasse in std::map on Mon, 11 May 2009 12:11:11 GMT]]></title><description><![CDATA[<p>Okay, ich denke ich werde dann die <code>ptr_map</code> verwenden. Kann man bei dieser eigentlich nicht den <code>operator[]</code> benutzen? Dann bringt er mich nämlich den Fehler, dass zB. <code>Scanner*</code> nicht in <code>Base&amp;</code> konvertiert werden kann. Macht aber auch nix, ich verwende dann halt die insert-Funktion:</p>
<pre><code class="language-cpp">/*
 *   boost::ptr_map
 */
typedef boost::ptr_map&lt;std::string, Base&gt; ptrMap;

ptrMap map;
map.insert(std::string(&quot;drucker&quot;), new Drucker());
map.insert(std::string(&quot;scanner&quot;), new Scanner());
//map[&quot;zweiterscanner&quot;] = new Scanner(); // geht nicht: C2679

ptrMap::iterator mit = map.find(std::string(&quot;drucker&quot;));
for(mit=map.begin();mit != map.end();mit++)
{
	mit-&gt;second-&gt;print();
}
map.clear();
std::cout &lt;&lt; map.size();
</code></pre>
<p>Übrigens, wieso klappt folgendes nicht:</p>
<pre><code class="language-cpp">typedef std::map&lt;std::string, Base*&gt; Map;
typedef boost::shared_ptr&lt;Base&gt; BasePtr;
typedef std::map&lt;std::string, BasePtr&gt; BMap;
typedef boost::ptr_map&lt;std::string, Base&gt; ptrMap;

Map map;
map[&quot;blabla&quot;] = new Scanner();

BMap bmap;
bmap[&quot;blub&quot;] = new Drucker();

ptrMap pmap;
pmap.insert(&quot;scanner&quot;, new Scanner()); // const char[8] kann nicht zu std::string konvertiert werden...
// oben gings doch auch :D
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1708945</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1708945</guid><dc:creator><![CDATA[issen1]]></dc:creator><pubDate>Mon, 11 May 2009 12:11:11 GMT</pubDate></item></channel></rss>