<?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[Frage zum State Pattern in C++]]></title><description><![CDATA[<p>Moin!</p>
<p>Ich hab da eine Anwendung für die sich das State Pattern eignet. Nach diverser Recherche, u.a. <a href="http://www.c-plusplus.net/forum/242984" rel="nofollow">http://www.c-plusplus.net/forum/242984</a> von Markus, bin ich mir jetzt allerdings unsicher, wie man das in C++ realisiert.</p>
<p>In den meisten Tutorials gibt es z.B. eine Klasse Monster, die einen bestimmten Zustand besitzt:</p>
<pre><code class="language-cpp">class Monster {
Zustand *pAktuellerZustand;
public:
void MachWas() { pAktuellerZustand-&gt;MachWas() };
void aendereZustand(Zustand *pNeuerZustand);

// [...]

};
</code></pre>
<p>Und eine Basisklasse für die Zustände:</p>
<pre><code class="language-cpp">class Zustand{
	public:
		Zustand(Monster *pMonster);
		virtual void MachWas() = 0;
		virtual ~Zustand(){};

	protected:
		Monster *pMonster;
};
</code></pre>
<p>Die Zustandsänderung erfolgt in den Zuständen selber, was ich so auch richtig finde. D.h. innerhalb einer Methode einer abgeleiteten Zustandsklasse wird geprüft, ob Bedingungen erfüllt sind und dann wird im Zustand selber ein neuer Zustand gesetzt. Das wird immer so realisiert:</p>
<p>z.B. im Zustand Aengstlich:</p>
<pre><code class="language-cpp">void Zustand_Aengstlich::MachWas() {
	// Renne wild umher

        if(GesundheitGefunden == true) {
              pMonster-&gt;aendereZustand(new Zustand_Kampfbereit(pMonster));
        }
}
</code></pre>
<p>aendereZustand ist wie folgt definiert:</p>
<pre><code class="language-cpp">void Monster::aendereZustand(Zustand *pNeuerZustand) {
    delete pAktuellerZustand; 
    pAktuellerZustand= pNeuerZustand;
}
</code></pre>
<p>Was ich nicht raffe:</p>
<p>Aufgerufen wird das ja wie folgt:</p>
<p>Monster::MachWas() ruft vom aktuellen Zustand Zustand::MachWas() auf. Innerhalb dieser Methode wird dann vom Monster Monster::aendereZustand() aufgerufen, wo die zugehörige Klasse/der Zustand der aufrufenden Methode ja gelöscht wird:</p>
<pre><code class="language-cpp">delete pAktuellerZustand;
</code></pre>
<p>Erst dann wird der neue Zustand gesetzt. Ist das überhaupt erlaubt? Schließlich könnte ja nach dem Setzen des Zustandes in der Zustand::MachWas() noch auf Klassenattribute o.ä. zugegriffen werden <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="😕"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/26a0.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--warning"
      title=":warning:"
      alt="⚠"
    /></p>
<p>Wie wird das State Pattern korrekt implementiert? Oder ist das so korrekt?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/282362/frage-zum-state-pattern-in-c</link><generator>RSS for Node</generator><lastBuildDate>Sun, 23 Aug 2026 07:14:00 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/282362.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 18 Feb 2011 16:12:22 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Frage zum State Pattern in C++ on Fri, 18 Feb 2011 16:12:22 GMT]]></title><description><![CDATA[<p>Moin!</p>
<p>Ich hab da eine Anwendung für die sich das State Pattern eignet. Nach diverser Recherche, u.a. <a href="http://www.c-plusplus.net/forum/242984" rel="nofollow">http://www.c-plusplus.net/forum/242984</a> von Markus, bin ich mir jetzt allerdings unsicher, wie man das in C++ realisiert.</p>
<p>In den meisten Tutorials gibt es z.B. eine Klasse Monster, die einen bestimmten Zustand besitzt:</p>
<pre><code class="language-cpp">class Monster {
Zustand *pAktuellerZustand;
public:
void MachWas() { pAktuellerZustand-&gt;MachWas() };
void aendereZustand(Zustand *pNeuerZustand);

// [...]

};
</code></pre>
<p>Und eine Basisklasse für die Zustände:</p>
<pre><code class="language-cpp">class Zustand{
	public:
		Zustand(Monster *pMonster);
		virtual void MachWas() = 0;
		virtual ~Zustand(){};

	protected:
		Monster *pMonster;
};
</code></pre>
<p>Die Zustandsänderung erfolgt in den Zuständen selber, was ich so auch richtig finde. D.h. innerhalb einer Methode einer abgeleiteten Zustandsklasse wird geprüft, ob Bedingungen erfüllt sind und dann wird im Zustand selber ein neuer Zustand gesetzt. Das wird immer so realisiert:</p>
<p>z.B. im Zustand Aengstlich:</p>
<pre><code class="language-cpp">void Zustand_Aengstlich::MachWas() {
	// Renne wild umher

        if(GesundheitGefunden == true) {
              pMonster-&gt;aendereZustand(new Zustand_Kampfbereit(pMonster));
        }
}
</code></pre>
<p>aendereZustand ist wie folgt definiert:</p>
<pre><code class="language-cpp">void Monster::aendereZustand(Zustand *pNeuerZustand) {
    delete pAktuellerZustand; 
    pAktuellerZustand= pNeuerZustand;
}
</code></pre>
<p>Was ich nicht raffe:</p>
<p>Aufgerufen wird das ja wie folgt:</p>
<p>Monster::MachWas() ruft vom aktuellen Zustand Zustand::MachWas() auf. Innerhalb dieser Methode wird dann vom Monster Monster::aendereZustand() aufgerufen, wo die zugehörige Klasse/der Zustand der aufrufenden Methode ja gelöscht wird:</p>
<pre><code class="language-cpp">delete pAktuellerZustand;
</code></pre>
<p>Erst dann wird der neue Zustand gesetzt. Ist das überhaupt erlaubt? Schließlich könnte ja nach dem Setzen des Zustandes in der Zustand::MachWas() noch auf Klassenattribute o.ä. zugegriffen werden <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="😕"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/26a0.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--warning"
      title=":warning:"
      alt="⚠"
    /></p>
<p>Wie wird das State Pattern korrekt implementiert? Oder ist das so korrekt?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022895</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022895</guid><dc:creator><![CDATA[StateOfTheArt]]></dc:creator><pubDate>Fri, 18 Feb 2011 16:12:22 GMT</pubDate></item><item><title><![CDATA[Reply to Frage zum State Pattern in C++ on Fri, 18 Feb 2011 17:08:36 GMT]]></title><description><![CDATA[<p>Sofern möglich kannst du die abgeleiteten States als Singletone implementieren, dann musst du diese nicht so unsauber löschen. Der Code ist halt nicht sicher. Du könntest std::swap verwenden und danach löschen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022921</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022921</guid><dc:creator><![CDATA[HighLigerBiMBam]]></dc:creator><pubDate>Fri, 18 Feb 2011 17:08:36 GMT</pubDate></item><item><title><![CDATA[Reply to Frage zum State Pattern in C++ on Fri, 18 Feb 2011 23:24:48 GMT]]></title><description><![CDATA[<p>I want MultiPartMonsters (aka 'More Brain to MonsterS):</p>
<p>Ich würde da warscheinlich eher beim &quot;Erschaffen&quot; des Monsters alle 'mögliche' Zustände mitgeben und intern einfach nur umschalten ... nicht zuweisen und zerstören</p>
<pre><code class="language-cpp">enum Dir    { moveN, moveE, moveS, moveW, moveU, moveD };
enum State  { deadState = 0, aliveState, hungryState, sleepyState, angryState, curiousState, lookingForIcecreamState, cryingState, surprisedState};
enum Event  { evNothing = 0, evHpLoss, evHpGain, evHungryer, evFoodFound, evPlaymateFound, evScornedBySomeone, evDunnoWhatEver };

class MultiPartMonster;

class Brain {
   MultiPartMonster * myMonster;
   std::set&lt;State&gt; states;
   State curState;
public:
   Brain(std::set&lt;State&gt; ls) : myMonster(0), states(ls) { curState = *states.begin(); }
   void setMonster(MultiPartMonster &amp;m) { if (!myMonster) myMonster = &amp;m; } // no brain surgery allowed
   void addState(const State &amp; s) { states.insert(s); }
   void process(const Event &amp;e);
};

struct Heart { int liveForce; };

struct Stomach { int hunger; };

struct Legs { int speed;  void walk() {};  void flee() {}; };

struct Kidneys { int pullerAlarm; void piss() {} };

struct Arms { int Strength;   void attack() {} }; 

class MultiPartMonster  {
  friend class Brain;
  Brain brain;
  Heart heart;
  Stomach stomach;
  Legs legs;
  Arms arms;
  Kidneys kidneys;
  // ...
public:
  MultiPartMonster(const std::set&lt;State&gt; &amp; ls) : brain(Brain(ls)) { brain.setMonster(*this); }
  void addState(const State&amp; s) { brain.addState(s); }
  void newTurn(const Event &amp; e) { brain.process(e); }
};

/* use/manipulate/query Monstermembers depending on currentState and incoming event */
void Brain::process(const Event &amp;e)  
{  
    if (e == evScornedBySomeone)
    {
      if (curState == angryState) { myMonster-&gt;arms.Strength = 30; myMonster-&gt;arms.attack(); }
      if (curState == curiousState) { myMonster-&gt;legs.walk(); }
    }    
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2023100</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2023100</guid><dc:creator><![CDATA[padreigh]]></dc:creator><pubDate>Fri, 18 Feb 2011 23:24:48 GMT</pubDate></item><item><title><![CDATA[Reply to Frage zum State Pattern in C++ on Sun, 20 Feb 2011 11:16:37 GMT]]></title><description><![CDATA[<p>Gerade das letzte Beispiel zeigt einen großen Nachteil, wenn man (bei vielen, komplexen Zuständen!) kein State Pattern verwendet. Das Aufschlüsseln der einzelnen Fälle und Aktionen wird komplex, kompliziert, möglicherweise fehleranfälliger, schwerer wartbar (da unübersichtlich) und erweiterbar (Änderung direkt an der Schnittstelle).</p>
<p>Zudem: Was passiert, wenn es spezifische Zustandsvariablen gibt, sprich für States gibt es eigene Member. Willst du die alle in deine Klasse packen, die zustandsbehaftet ist? Gerade Zustände sollten nach aussen hin (zum Client) nicht sichtbar sein.</p>
<p>@TE: Das Löschen und Neu-Setzen von Zuständen hast _du_ ja in der Hand, also dürfte auch nicht keine Gefahr bestehen. Der Vorschlag von <strong>HighLigerBiMBam</strong> dagegen ist gut, verhindert, dass im Fall des Falles ein undefinierter Zustand existiert.</p>
<p>HTH</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2023607</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2023607</guid><dc:creator><![CDATA[[[global:former_user]]]]></dc:creator><pubDate>Sun, 20 Feb 2011 11:16:37 GMT</pubDate></item></channel></rss>