<?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[Exception oder nullptr?]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich bin aktuell über einige Exception-Artikel gestolpert und nun völlig unsicher, wann ich eine Exception werfen soll oder wann ein nullptr als Rückgabewert im Fehlerfall genügt.</p>
<p>Angenommen es gibt eine Klasse, die Ressourcen in einem Array verwaltet. Das Array wird zu Beginn in festgelegter Größe erzeugt und mit &quot;Leerdaten&quot; gefüllt. Weiterhin besitzt diese Klasse die zu verwaltenden Objekte.</p>
<p>Nun fallen mir mindestens 3 Operationen ein, bei denen ich mir teilweise unsicher bin, was ich im Fehlerfall tun sollte. Möglichkeit 1 wäre komplett über Exceptions zu gehen:</p>
<pre><code class="language-cpp">void set( std::size_t index, const Foo&amp; value ); // 1
const Foo&amp; get( std::size_t index ) const; // 2
void create( std::size_t index ); // 3
</code></pre>
<p>(1) setzt einen neuen Wert. Darf aber nur gehen, wenn der index gültig ist.<br />
(2) holt einen Wert. Darf aber nur gehen, wenn index gültig ist und bei index ein Wert liegt (d.h. vorher per create() angelegt bzw. set() gesetzt).<br />
(3) erzeugt einen Wert. Darf aber nur gehen, wenn index gültig ist und bei index noch kein Wert liegt.</p>
<p>Möglichkeit 2 wären bool'sche Rückgabewerte und nullptr:</p>
<pre><code class="language-cpp">bool set( std::size_t index, const Foo&amp; value ); // 1
const Foo* get( std::size_t index ) const; // 2
bool create( std::size_t index ); // 3
</code></pre>
<p>Bei der 2. Möglichkeit könnte ich mir auch eine Mischung vorstellen. Das heißt: Exception werfen, falls index ungültig ist, denn in diesem Fall liegt ein Programmierfehler vor. Hingegen ist für so etwas ja assert() da...</p>
<p>Es wäre super, wenn jemand dazu ein paar Ideen/Erfahrungen hätte. Ich möchte meinen Code gerne so schreiben, dass Fehler schnell auffallen und es ergo schwer ist, ihn falsch zu benutzen. Aber anders herum erscheint mit manches in Möglichkeit 1 so umständlich (z.B. müsste ein Benutzer vorher abfragen, ob ein Wert existiert, bevor er ihn mit get() holen kann, damit der Fehlerfall vermieden wird und es nicht zu einer Exception kommt).</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/297150/exception-oder-nullptr</link><generator>RSS for Node</generator><lastBuildDate>Fri, 14 Aug 2026 16:15:28 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/297150.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 20 Dec 2011 02:39:33 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 02:39:33 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich bin aktuell über einige Exception-Artikel gestolpert und nun völlig unsicher, wann ich eine Exception werfen soll oder wann ein nullptr als Rückgabewert im Fehlerfall genügt.</p>
<p>Angenommen es gibt eine Klasse, die Ressourcen in einem Array verwaltet. Das Array wird zu Beginn in festgelegter Größe erzeugt und mit &quot;Leerdaten&quot; gefüllt. Weiterhin besitzt diese Klasse die zu verwaltenden Objekte.</p>
<p>Nun fallen mir mindestens 3 Operationen ein, bei denen ich mir teilweise unsicher bin, was ich im Fehlerfall tun sollte. Möglichkeit 1 wäre komplett über Exceptions zu gehen:</p>
<pre><code class="language-cpp">void set( std::size_t index, const Foo&amp; value ); // 1
const Foo&amp; get( std::size_t index ) const; // 2
void create( std::size_t index ); // 3
</code></pre>
<p>(1) setzt einen neuen Wert. Darf aber nur gehen, wenn der index gültig ist.<br />
(2) holt einen Wert. Darf aber nur gehen, wenn index gültig ist und bei index ein Wert liegt (d.h. vorher per create() angelegt bzw. set() gesetzt).<br />
(3) erzeugt einen Wert. Darf aber nur gehen, wenn index gültig ist und bei index noch kein Wert liegt.</p>
<p>Möglichkeit 2 wären bool'sche Rückgabewerte und nullptr:</p>
<pre><code class="language-cpp">bool set( std::size_t index, const Foo&amp; value ); // 1
const Foo* get( std::size_t index ) const; // 2
bool create( std::size_t index ); // 3
</code></pre>
<p>Bei der 2. Möglichkeit könnte ich mir auch eine Mischung vorstellen. Das heißt: Exception werfen, falls index ungültig ist, denn in diesem Fall liegt ein Programmierfehler vor. Hingegen ist für so etwas ja assert() da...</p>
<p>Es wäre super, wenn jemand dazu ein paar Ideen/Erfahrungen hätte. Ich möchte meinen Code gerne so schreiben, dass Fehler schnell auffallen und es ergo schwer ist, ihn falsch zu benutzen. Aber anders herum erscheint mit manches in Möglichkeit 1 so umständlich (z.B. müsste ein Benutzer vorher abfragen, ob ein Wert existiert, bevor er ihn mit get() holen kann, damit der Fehlerfall vermieden wird und es nicht zu einer Exception kommt).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159069</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159069</guid><dc:creator><![CDATA[sboc]]></dc:creator><pubDate>Tue, 20 Dec 2011 02:39:33 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 03:27:47 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">bool set( std::size_t index, const Foo&amp; value, bool throw_exception = false );
const Foo* get( std::size_t index, bool throw_exception = false ) const;
bool create( std::size_t index, bool throw_exception = false );
</code></pre>
<p>Wenn die Klasse eh nur in einem größeren Kontext Sinn macht, in dem Exceptions auf höherer Ebene gefangen werden (z.B. in einem Spiel), dann kannst du auch gleich Variante 1 nehmen. Ansonsten weißt du nicht wie der &quot;Nutzer&quot; der Klasse diese Funktionen nutzen möchte, warum also nicht ihm die Wahl überlassen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159071</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159071</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Tue, 20 Dec 2011 03:27:47 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 05:24:23 GMT]]></title><description><![CDATA[<p>sboc schrieb:</p>
<blockquote>
<p>Hingegen ist für so etwas ja assert() da...</p>
</blockquote>
<p>Genau, und das eigentlich für alle 3.</p>
<blockquote>
<p>Es wäre super, wenn jemand dazu ein paar Ideen/Erfahrungen hätte. Ich möchte meinen Code gerne so schreiben, dass Fehler schnell auffallen und es ergo schwer ist, ihn falsch zu benutzen. Aber anders herum erscheint mit manches in Möglichkeit 1 so umständlich (z.B. müsste ein Benutzer vorher abfragen, ob ein Wert existiert, bevor er ihn mit get() holen kann, damit der Fehlerfall vermieden wird und es nicht zu einer Exception kommt).</p>
</blockquote>
<p>Du baust irgendwie sowas wie std::vector nach, aber create mit index könnte auch wieder std::map sein. Sieht irgendwie komisch aus dein Design. Warum spricht man Ressourcen per index an? Was für Ressourcen überhaupt?</p>
<p>cooky451 schrieb:</p>
<blockquote>
<pre><code class="language-cpp">bool set( std::size_t index, const Foo&amp; value, bool throw_exception = false );
const Foo* get( std::size_t index, bool throw_exception = false ) const;
bool create( std::size_t index, bool throw_exception = false );
</code></pre>
</blockquote>
<p>Schrecklich.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159073</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159073</guid><dc:creator><![CDATA[Smilies in diesem Beitrag]]></dc:creator><pubDate>Tue, 20 Dec 2011 05:24:23 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 08:47:31 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>der Vorteil von Exceptions ist, daß im Aufrufstack zwischen der Fehlerursache und der Fehlerbehandlung viele Routinen stehen können, die sich nicht um den Fehler kümmern müssen, weil der erforderliche Code vom Compiler automatisch generiert wird. Nur solche Funktionen, die Ressourcen angefordert haben, müssen auf den Fehler reagieren, brauchen sich aber nicht um die Art des Fehler kümmern:</p>
<pre><code class="language-cpp">void *foo( void )
{
    void *ptr = malloc( 100000 );
    try
    (
         do_something( ptr );
    }
    catch( ... )
    {
        free( ptr );
        throw;
    }
    return ptr;
}
</code></pre>
<p>Funktionen, die statt eine Exception zu werfen einen Fehlercode zurückliefern, müssen sich darauf verlassen, daß der direkte Aufrufer dann auch darauf reagiert.</p>
<p>Wenn dies der Fall ist, benutze ich lieber den Fehlercode, weil das für mich meistens einfacher zu realisieren ist:</p>
<pre><code class="language-cpp">FILE *foo( void )
{
    FILE *ptr = fopen( &quot;temp.txt&quot;, &quot;r&quot; );
    if( !ptr )
    {
         ptr = fopen( &quot;temp.old&quot;, &quot;r&quot; );
    }

    return ptr;
}
</code></pre>
<p>Wenn fopen stattdessen 'ne Exception werfen würde, müsste der Code so ausschauen:</p>
<pre><code class="language-cpp">FILE *foo( void )
{
    FILE *ptr;

    try
    {
        ptr = fopen( &quot;temp.txt&quot;, &quot;r&quot; );
    }
    catch( ... )
    {
         ptr = fopen( &quot;temp.old&quot;, &quot;r&quot; );
    }

    return ptr;
}
</code></pre>
<p>Ist jetzt vielleicht ein blödes Beispiel, weil mir auf die schnelle nix besseres einfällt, aber ich denke man sieht, was ich meine.</p>
<p>Es kommt halt auch immer darauf an, wie das Programm im Fehlerfall reagiert.</p>
<p>Wenn Du ganz ohne Exceptions auskommst, kann der Compiler auch den ganzen automatisch generierten Code weglassen, was Dein Programm unter Umständen schneller machen kann. Ich denke aber, daß in vielen Fällen der Vorteil der Exceptions aber überwiegt.</p>
<p>mfg Martin</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159106</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159106</guid><dc:creator><![CDATA[mgaeckler]]></dc:creator><pubDate>Tue, 20 Dec 2011 08:47:31 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 09:27:22 GMT]]></title><description><![CDATA[<p>Smilies in diesem Beitrag schrieb:</p>
<blockquote>
<p>Schrecklich.</p>
</blockquote>
<p>Weil?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159126</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159126</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Tue, 20 Dec 2011 09:27:22 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 10:34:16 GMT]]></title><description><![CDATA[<p>cooky451 schrieb:</p>
<blockquote>
<p>Smilies in diesem Beitrag schrieb:</p>
<blockquote>
<p>Schrecklich.</p>
</blockquote>
<p>Weil?</p>
</blockquote>
<p>Weil ich schrecklichen Code erkenne. :p<br />
Was bringt das, wenn ich es sowieso nur da setzen kann, wo ich auch gleich den Rückgabewert prüfen kann? Da kommen mir nur so komische Fragen wie: Muss man den return Wert jetzt immer noch anschauen? Haben die das gebaut, weil der Code über irgendeine Schnittstelle aufgerufen wird, die keine Exceptions kann?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159155</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159155</guid><dc:creator><![CDATA[Smilies in diesem Beitrag]]></dc:creator><pubDate>Tue, 20 Dec 2011 10:34:16 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 10:48:40 GMT]]></title><description><![CDATA[<p>Smilies in diesem Beitrag schrieb:</p>
<blockquote>
<p>Was bringt das, wenn ich es sowieso nur da setzen kann, wo ich auch gleich den Rückgabewert prüfen kann?</p>
</blockquote>
<p>Na ja, dass man sich beide Möglichkeiten offen hält? Man könnte auch gleich ein obj.enableExceptions(); oder so einführen, aber grundsätzlich ist die Idee ja die Gleiche. Denn niemand will solchen Code sehen:</p>
<pre><code class="language-cpp">int main()
{
  KomischeKlasse obj;
  try
  {
    obj.foo();
  }
  catch (KomischeKlasseException &amp;e)
  {
  }
}
</code></pre>
<p>Und so etwas ist natürlich noch schlimmer:</p>
<pre><code class="language-cpp">int main()
{
  KomischeKlasse obj;
  if (obj.foo())
  {
    if (obj.bar())
    {
      if(obj.baz())
      {
      }
      else
      {
      }
    }
    else
    {
    }
  }
  else
  {
  }
}
</code></pre>
<p>Solange man also beim schreiben der Klasse nicht erraten kann, wie das Programm des Nutzers aussieht, sollte man ihm doch ruhig die Wahl lassen. assert() würde ich dagegen nur in Debug-Code nutzen und auch nur um auf offensichtliche Programmierfehler aufmerksam zu machen. Um Laufzeitfehler (im Sinne von &quot;Datei nicht vorhanden&quot; etc.) abzufangen halte ich assert() doch für mehr als unpassend, den Fehler kann man dann ja auch nicht mal mehr behandeln.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159160</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159160</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Tue, 20 Dec 2011 10:48:40 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 10:50:45 GMT]]></title><description><![CDATA[<p>cooky451 schrieb:</p>
<blockquote>
<pre><code class="language-cpp">int main()
{
  KomischeKlasse obj;
  try
  {
    obj.foo();
  }
  catch (KomischeKlasseException &amp;e)
  {
  }
}
</code></pre>
</blockquote>
<p>Äh, nein. Genau so solls sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159161</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159161</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Tue, 20 Dec 2011 10:50:45 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 11:15:09 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>Äh, nein. Genau so solls sein.</p>
</blockquote>
<p>Das ist dir lieber als:</p>
<pre><code class="language-cpp">int main()
{
  KomischeKlasse obj;
  if (obj.foo())
  {
  }
}
</code></pre>
<p>? Komisch, ich habe dich noch nie mit Filestream-Exceptions hantieren sehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159170</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159170</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Tue, 20 Dec 2011 11:15:09 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 11:17:47 GMT]]></title><description><![CDATA[<p>Bastelst du also bei jeder deiner Klassen dieses setstate-Zeugs drumherum?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159171</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159171</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Tue, 20 Dec 2011 11:17:47 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 11:28:09 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>Bastelst du also bei jeder deiner Klassen dieses setstate-Zeugs drumherum?</p>
</blockquote>
<p>Solange ich nicht einschätzen kann wie die Klasse genutzt wird, mache ich es wie oben vorgeschlagen. Es mag sicher Klassen geben bei denen es sinnvoll ist immer zu werfen, aber das ist hier ja nicht der Fall.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159175</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159175</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Tue, 20 Dec 2011 11:28:09 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 11:57:26 GMT]]></title><description><![CDATA[<p>So ein Flag bei allen Funktionen verschandelt die ganze API! Wenn jemand lieber mit exceptions arbeitet, muss er immer ein &quot;true&quot; mitgeben. Wenn der letzte ordentliche Parameter ein bool ist, wirds auch noch ganz verzwickt, wenn man das letzte &quot;true&quot; für das &quot;throwException-Flag&quot; hält. Braucht man dafür ein false und geht später über den Code, ist die Versuchung groß, den Code anzupassen, und das false in ein true zu ändern, obwohl es gar nix mehr mit dem exception-flag zu tun hat.<br />
Außerdem muss jede Funktion das Flag prüfen und entsprechend den einen oder anderen Codepfad ausführen - das bläht unnötig auf.</p>
<p>Da jemand entweder volles Rohr auf Exceptions steht (wo sie auch Sinn machen!) oder sie abgrundtief hasst (mir ist noch kaum jemand dazwischen begegnet), ist die einzige saubere Lösung, wenn man wirklich beides anbieten will, ein Präprozesor-Flag, das exceptions anmacht oder auf returncodes ausweicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159184</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159184</guid><dc:creator><![CDATA[destroying angel]]></dc:creator><pubDate>Tue, 20 Dec 2011 11:57:26 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 12:27:53 GMT]]></title><description><![CDATA[<p>cooky451 schrieb:</p>
<blockquote>
<p>314159265358979 schrieb:</p>
<blockquote>
<p>Bastelst du also bei jeder deiner Klassen dieses setstate-Zeugs drumherum?</p>
</blockquote>
<p>Solange ich nicht einschätzen kann wie die Klasse genutzt wird, mache ich es wie oben vorgeschlagen. Es mag sicher Klassen geben bei denen es sinnvoll ist immer zu werfen, aber das ist hier ja nicht der Fall.</p>
</blockquote>
<p>Schlechte Idee.<br />
Ein sinnvoller Stil ist immer besser als alle Stile die man findet zu vermischen.</p>
<p>Entweder man wirft Exception oder man wirft keine. Umschalten ist dämlich. Gibt auch genug Diskussionen warum es in der C++ Library mit den Filestreams ziemlich kacke ist.</p>
<p>Das Flag ist halt furchtbar, weil man nie weiss was jetzt passiert. Ist der Code Exception sicher oder nicht? Man weiss es nicht weil das Ding vielleicht wirft, vielleicht auch nicht. Also muss ich immer alles checken. Das ist einfach nicht gut.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159199</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159199</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Tue, 20 Dec 2011 12:27:53 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 12:32:38 GMT]]></title><description><![CDATA[<p>destroying angel schrieb:</p>
<blockquote>
<p>..obwohl es gar nix mehr mit dem exception-flag zu tun hat.</p>
</blockquote>
<p>Ja, das könnte passieren. Aber nicht bei drei Funktionen mit 1-2 Parametern. Eventuell müsste man dann doch noch auf eine flag-Funktion ausweichen.</p>
<p>destroying angel schrieb:</p>
<blockquote>
<p>Außerdem muss jede Funktion das Flag prüfen und entsprechend den einen oder anderen Codepfad ausführen - das bläht unnötig auf.</p>
</blockquote>
<p>Nein. Die Bedingung die die Exception auslösen soll muss eh geprüft werden, da wird halt noch ein &quot; &amp;&amp; throw_exception&quot; angehangen. Was den Code aufbläht, sind #ifdefs in jeder Funktion. <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>Shade Of Mine schrieb:</p>
<blockquote>
<p>Ein sinnvoller Stil ist immer besser als alle Stile die man findet zu vermischen.</p>
</blockquote>
<p>Aber nicht wenn man den Stil mit dem die Klasse genutzt werden soll gar nicht kennt.</p>
<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Das Flag ist halt furchtbar, weil man nie weiss was jetzt passiert.</p>
</blockquote>
<p>Kannst du mir dafür mal ein Beispiel nennen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159200</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159200</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Tue, 20 Dec 2011 12:32:38 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 12:38:05 GMT]]></title><description><![CDATA[<p>sboc schrieb:</p>
<blockquote>
<pre><code class="language-cpp">void set( std::size_t index, const Foo&amp; value ); // 1
const Foo&amp; get( std::size_t index ) const; // 2
void create( std::size_t index ); // 3
</code></pre>
</blockquote>
<p>Es hängt natürlich vom Anwendungsfall ab, aber ich würd im Allgemeinen da eher in allen 3 Fällen wenn überhaupt dann ein assert() verwenden. Alternativ könnte man dem Container-Template eine Range-Checking-Policy als Argument geben, die dann wahlweise eine Exception wirft. Oder man macht es so wie die std:: Container und bietet zwei Methoden an, eine die eine Exception wirft und eine die's nicht tut.<br />
Die Methode <code>create()</code> könnte den alten Wert zurückgeben, oder einen bool der sagt ob der Wert schon vorhanden war und überschrieben wurde.<br />
Rückgabewerte für Index of out Bounds wären da imo jedenfalls ziemlich fehl am Platz.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159202</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159202</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Tue, 20 Dec 2011 12:38:05 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 12:50:56 GMT]]></title><description><![CDATA[<p>cooky451: Glaub es einfach, mindestens 3 Leute sagen schon, dass es schrecklich ist.</p>
<p>sboc: Warum brauchst man überhaupt eine create und eine set Methode? Die create Methode hat nicht mal Zusatzparameter, wie etwas erstellt werden soll. Das sieht alles sehr komisch aus. Was soll das am Ende tun (Beispiel).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159207</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159207</guid><dc:creator><![CDATA[Smilies in diesem Beitrag]]></dc:creator><pubDate>Tue, 20 Dec 2011 12:50:56 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 13:23:16 GMT]]></title><description><![CDATA[<p>Zunächst vielen Dank für die Antworten. Da habe ich ja fast vermutet, dass ein kleiner Glaubenskrieg ausbricht. :xmas1:</p>
<p>Smilies in diesem Beitrag schrieb:</p>
<blockquote>
<p>Warum brauchst man überhaupt eine create und eine set Methode?</p>
</blockquote>
<p>Das ist nur wg. des Beispiels so. Diese drei Operationen sind mir prompt eingefallen, bei denen ich mir unsicher bin, wie ich das handeln soll. Tatsächlich würden z.B. nur &quot;set&quot; und &quot;get&quot; gemeinsam in einer Klasse auftauchen, &quot;create&quot; dann separat in einer anderen.</p>
<p>dot schrieb:</p>
<blockquote>
<p>Es hängt natürlich vom Anwendungsfall ab, aber ich würd im Allgemeinen da eher in allen 3 Fällen wenn überhaupt dann ein assert() verwenden.</p>
</blockquote>
<p>Das würde mir (technisch) auch völlig ausreichen. Blöderweise verträgt sich das assert() mit Boost.Test, das ich einsetze, nicht so gut. Auf Exceptions testen ist einfacher.</p>
<p>Im Falle der &quot;get&quot;-Methode tendiere ich mittlerweile zu einer Exception/nullptr-&quot;Kombination&quot;. Exception werfen, wenn der Parameter unsinnig ist, d.h. wirklich ein Programmierfehler vorliegt und nullptr (bzw. Fehlerwert) liefern, wenn zwar der Parameter gültig ist, an geeigneter Stelle aber nichts gefunden wird.</p>
<p>Ich möchte euch aber gerne noch mit einem konkreteren Beispiel verwöhnen, der vorige Code scheint teilweise mehr verwirrt als geholfen zu haben:</p>
<pre><code class="language-cpp">class Map {
	public:
		static const unsigned int INVALID_ID = std::numeric_limits&lt;unsigned int&gt;::max();

		Map( unsigned int size ) :
			m_tiles( size * size, INVALID_ID ),
			m_size( size )
		{
		}

		void set( unsigned int x, unsigned int y, unsigned int id ) {
			if( x &gt;= m_size || y &gt;= m_size ) {
				throw std::invalid_argument( &quot;x/y doof.&quot; );
			}
			else if( id == INVALID_ID ) {
				throw std::invalid_argument( &quot;id doof.&quot; );
			}

			m_tiles[y * m_size + x] = id;
		}

		void reset( unsigned int x, unsigned int y ) {
			if( x &gt;= m_size || y &gt;= m_size ) {
				throw std::invalid_argument( &quot;x/y doof.&quot; );
			}

			m_tiles[y * m_size + x] = INVALID_ID;
		}

		unsigned int get( unsigned int x, unsigned int y ) const {
			if( x &gt;= m_size || y &gt;= m_size ) {
				throw std::invalid_argument( &quot;x/y doof.&quot; );
			}

			return m_tiles[y * m_size + x];
		}

	private:
		std::vector&lt;unsigned int&gt; m_tiles;
		unsigned int m_size;
};
</code></pre>
<p>std::vector&lt;<strong>unsigned int</strong>&gt; ist der Einfachheit halber gewählt, es gibt den Fall auch mit größeren Ressourcen, die dann über Pointer rausgehen.<br />
Prinzipiell habe ich im Beispiel nun statt assert()s Exceptions genutzt und mich im get-Fall entschieden, einen Fehlerwert zurück zu geben, falls zwar die Koordinate korrekt ist, dort aber kein wirklicher Inhalt zu finden ist (INVALID_ID). Und falls wer meckert, dass das ja fast ein purer vector-Wrapper ist: Es gibt selbstverfreilich weitere Operationen. <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>Was haltet ihr davon?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159211</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159211</guid><dc:creator><![CDATA[sboc]]></dc:creator><pubDate>Tue, 20 Dec 2011 13:23:16 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 13:36:25 GMT]]></title><description><![CDATA[<p>Ich würde bei diesen Settern nur in der Debugversion mit asserts den Bereich und die IDs prüfen.</p>
<p>In der Releaseversion haben derlei Überprüfungen imho nichts zu suchen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159216</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159216</guid><dc:creator><![CDATA[Thorgrim]]></dc:creator><pubDate>Tue, 20 Dec 2011 13:36:25 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 13:38:04 GMT]]></title><description><![CDATA[<p>Dann bau dir ein assert() dass eine Exception wirft?<br />
Wenn dein Programmdesign vom Testsystem bestimmt wird, dann ist das Testsystem Mist oder du verwendest es falsch, wenn du mich fragst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159218</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159218</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Tue, 20 Dec 2011 13:38:04 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 13:49:58 GMT]]></title><description><![CDATA[<p>sboc schrieb:</p>
<blockquote>
<p>Blöderweise verträgt sich das assert() mit Boost.Test, das ich einsetze, nicht so gut. Auf Exceptions testen ist einfacher.</p>
</blockquote>
<p>Du brauchst auch nicht testen, was passiert, wenn man falsch programmiert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159222</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159222</guid><dc:creator><![CDATA[Smilies in diesem Beitrag]]></dc:creator><pubDate>Tue, 20 Dec 2011 13:49:58 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 15:08:14 GMT]]></title><description><![CDATA[<p>dot schrieb:</p>
<blockquote>
<p>Dann bau dir ein assert() dass eine Exception wirft?<br />
Wenn dein Programmdesign vom Testsystem bestimmt wird, dann ist das Testsystem Mist oder du verwendest es falsch, wenn du mich fragst.</p>
</blockquote>
<p>Könnte es nicht auch ein Hinweis darauf sein, dass das Design kein anständiges Testen zulässt? Ich schreibe zuerst Unittests, bevor ich den Produktiv-Code schreibe, und dort möchte ich halt auch Fehler provozieren, wo sie auftauchen <strong>sollen</strong>.</p>
<blockquote>
<p>Du brauchst auch nicht testen, was passiert, wenn man falsch programmiert.</p>
</blockquote>
<p>Ich denke schon, dass das sinnvoll ist. Ich möchte ja z.B. durch einen Testfall sicherstellen, dass eine Funktion bei falschen Werten fehlerhaft reagiert. Das wäre vergleichbar damit, als würde man nur testen, ob 15 / 5 = 3, aber nicht ob 15 / 0 = Fehler.</p>
<p>Dass etwas bei anständigen Werten funktioniert, ist ja nur die halbe Miete. Oder aber ich mache es tatsächlich falsch, bin noch recht frisch beim test-driven development.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159264</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159264</guid><dc:creator><![CDATA[sboc]]></dc:creator><pubDate>Tue, 20 Dec 2011 15:08:14 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 15:22:26 GMT]]></title><description><![CDATA[<p>sboc schrieb:</p>
<blockquote>
<p>dot schrieb:</p>
<blockquote>
<p>Dann bau dir ein assert() dass eine Exception wirft?<br />
Wenn dein Programmdesign vom Testsystem bestimmt wird, dann ist das Testsystem Mist oder du verwendest es falsch, wenn du mich fragst.</p>
</blockquote>
<p>Könnte es nicht auch ein Hinweis darauf sein, dass das Design kein anständiges Testen zulässt? Ich schreibe zuerst Unittests, bevor ich den Produktiv-Code schreibe, und dort möchte ich halt auch Fehler provozieren, wo sie auftauchen <strong>sollen</strong>.</p>
</blockquote>
<p>Wenn du mich fragst soll das Testsystem sich dem Programm anpassen und nicht umgekehrt. Denn ich schreib das Programm ja nicht damit ich was zu testen hab, sondern aus anderen Gründen...<br />
Im konkreten Fall würd ich mal ganz definitiv sagen, dass mit Testsystem grob was im argen liegt, wenn es so grundlegende Entscheidungen wie das Verhalten einer Containerklasse beeinflusst oO</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159273</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159273</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Tue, 20 Dec 2011 15:22:26 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 15:50:49 GMT]]></title><description><![CDATA[<p>dot schrieb:</p>
<blockquote>
<p>Wenn du mich fragst soll das Testsystem sich dem Programm anpassen und nicht umgekehrt. Denn ich schreib das Programm ja nicht damit ich was zu testen hab, sondern aus anderen Gründen...</p>
</blockquote>
<p>Mit den Tests möchte ich auch nur sicherstellen, dass die Klasse sich genau so verhält wie gedacht. Das heißt, wenn ich die Tests schreibe, überlege ich, welche Fehler ich bei falschen Eingaben erwarte (neben den viel wichtigeren Erwartungen, was korrekterweise herauskommen soll, natürlich). Erst danach implementiere ich die Klasse nach diesem Schema.</p>
<blockquote>
<p>Im konkreten Fall würd ich mal ganz definitiv sagen, dass mit Testsystem grob was im argen liegt, wenn es so grundlegende Entscheidungen wie das Verhalten einer Containerklasse beeinflusst oO</p>
</blockquote>
<p>Ich weiß nicht genau, was du mit Beeinflussen meinst. Die Tests geben in meinem Fall das Design vor, da die Klasse so funktionieren soll wie die Tests sie nutzen (<a href="http://de.wikipedia.org/wiki/Testgetriebene_Entwicklung" rel="nofollow">TDD</a>, falls noch nicht bekannt).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159305</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159305</guid><dc:creator><![CDATA[sboc]]></dc:creator><pubDate>Tue, 20 Dec 2011 15:50:49 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 15:54:48 GMT]]></title><description><![CDATA[<p>sboc schrieb:</p>
<blockquote>
<p>dot schrieb:</p>
<blockquote>
<p>Wenn du mich fragst soll das Testsystem sich dem Programm anpassen und nicht umgekehrt. Denn ich schreib das Programm ja nicht damit ich was zu testen hab, sondern aus anderen Gründen...</p>
</blockquote>
<p>Mit den Tests möchte ich auch nur sicherstellen, dass die Klasse sich genau so verhält wie gedacht. Das heißt, wenn ich die Tests schreibe, überlege ich, welche Fehler ich bei falschen Eingaben erwarte (neben den viel wichtigeren Erwartungen, was korrekterweise herauskommen soll, natürlich). Erst danach implementiere ich die Klasse nach diesem Schema.</p>
</blockquote>
<p>Kann die Testumgebung denn nicht erwarten und testen, daß bei einem falschen Index ein assert zündet?<br />
Das wäre doch ok, dann könntest Du, wie es sich gehört, Programmierfehler mit assert begrenzen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159306</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159306</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Tue, 20 Dec 2011 15:54:48 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 15:54:45 GMT]]></title><description><![CDATA[<p>cooky451 schrieb:</p>
<blockquote>
<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Das Flag ist halt furchtbar, weil man nie weiss was jetzt passiert.</p>
</blockquote>
<p>Kannst du mir dafür mal ein Beispiel nennen?</p>
</blockquote>
<p>Klar:</p>
<pre><code class="language-cpp">void foo(Klasse&amp; obj) {
   obj.bar();
}

int main() {
   Klasse a;
   a.enable_exceptions(true);
   foo(a);

   Klasse b;
   b.enable_exceptions(false);
   foo(b);
}
</code></pre>
<p>Wie soll foo jetzt wissen wie es auf einen Fehler bei bar() reagieren soll? Jedesmal checken ob Exceptions aktiviert sind? Und wenn Exceptions aktiviert sind, wie ist dann isGood() oder failed() etc. definiert wenn eine Exception fliegt? Wird immer das fail bit immer gesetzt? Was wenn ich zwischen einem Fehler umschalte?</p>
<p>Enorme Komplexität für keinen Mehrwert. Wenn du einfach sagst bar() wirft eine Exception, dann ist alles klar. Keine Probleme, keine Unsicherheit - auch robuster Code.</p>
<p>Denn Stell dir vor du hast Unit Tests mit eingeschaltenen Exceptions und dann im Produktionscode werden sie irgendwo ausgeschalten. uU nur bei einem Objekt. Das führt zu unfindbaren Fehlern.</p>
<p>Deshalb ist es ganz wichtig: ein Weg! Eine Art Fehler zu reporten. Nicht 2. Nicht 3. Nur eine Art. Weil sonst werden die anderen irgendwann/irgendwo einmal übersehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159307</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159307</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Tue, 20 Dec 2011 15:54:45 GMT</pubDate></item><item><title><![CDATA[Reply to Exception oder nullptr? on Tue, 20 Dec 2011 15:58:56 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>Kann die Testumgebung denn nicht erwarten und testen, daß bei einem falschen Index ein assert zündet?<br />
Das wäre doch ok, dann könntest Du, wie es sich gehört, Programmierfehler mit assert begrenzen.</p>
</blockquote>
<p>Hast Du völlig Recht, aber soweit ich weiß, bietet zumindest Boost.Test das nicht an (es gibt einen Weg über einen Hack, aber das ist immer so eine Sache..). Vielleicht schaue ich mich mal bei anderen Frameworks um, wie die das unterstützen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2159309</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2159309</guid><dc:creator><![CDATA[sboc]]></dc:creator><pubDate>Tue, 20 Dec 2011 15:58:56 GMT</pubDate></item></channel></rss>