<?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[class member initialization]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>ich habe eine Klasse, die ua. ein array als private Attribut hat, welches ich im constructor zur Laufzeit dynamisch erstelle. Die Länge des Arrays wird in einer private const Variable gespeichert. Das ganze sieht also folgendermassen aus:</p>
<pre><code>class MyClass
{
  private:
    int *array;
    const int SIZE;

  public:
    MyClass(int s = 10) : SIZE(s) { array = new int [SIZE]; }
};
</code></pre>
<p>So, das ganze funktioniert auch so wie ich es will, das const int SIZE Attribut wird im constructor durch die member initialization entsprechend gesetzt, falls der constructor ohne Parameter aufgerufen wird, dann wird auch richtig der default value von 10 genommen.</p>
<p>ABER: was ist, wenn der Parameter &lt; 1 ist? Dann würde die Erstellung des Arrays keinen Sinn machen. Also habe ich versucht, den constructor folgendermassen zu erweitern:</p>
<pre><code>MyClass(int s = 10) : SIZE(s)
{
  if( s &lt; 1 )
    s = 10;

  array = new int [SIZE];
}
</code></pre>
<p>Dies führt aber nicht zum gewünschten Ergebnis, da das attribut SIZE anscheinend bereits vor der if-Abfrage gesetzt ist. Das heisst, ich ändere damit zwar im Falle von s &lt; 1 auf s = 10, aber das bringt mir nichts, weil das SIZE dadurch nicht mehr geändert wird.</p>
<p>Meine Frage also: Kann ich das irgendwie im constructor abfragen und ggf. ändern, BEVOR dss Attribut SIZE gesetzt wird?</p>
<p>Gruss und vielen Dank im Voraus!<br />
Matthias</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/199918/class-member-initialization</link><generator>RSS for Node</generator><lastBuildDate>Sun, 04 Oct 2026 04:40:43 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/199918.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 08 Dec 2007 15:01:37 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to class member initialization on Sat, 08 Dec 2007 15:01:37 GMT]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>ich habe eine Klasse, die ua. ein array als private Attribut hat, welches ich im constructor zur Laufzeit dynamisch erstelle. Die Länge des Arrays wird in einer private const Variable gespeichert. Das ganze sieht also folgendermassen aus:</p>
<pre><code>class MyClass
{
  private:
    int *array;
    const int SIZE;

  public:
    MyClass(int s = 10) : SIZE(s) { array = new int [SIZE]; }
};
</code></pre>
<p>So, das ganze funktioniert auch so wie ich es will, das const int SIZE Attribut wird im constructor durch die member initialization entsprechend gesetzt, falls der constructor ohne Parameter aufgerufen wird, dann wird auch richtig der default value von 10 genommen.</p>
<p>ABER: was ist, wenn der Parameter &lt; 1 ist? Dann würde die Erstellung des Arrays keinen Sinn machen. Also habe ich versucht, den constructor folgendermassen zu erweitern:</p>
<pre><code>MyClass(int s = 10) : SIZE(s)
{
  if( s &lt; 1 )
    s = 10;

  array = new int [SIZE];
}
</code></pre>
<p>Dies führt aber nicht zum gewünschten Ergebnis, da das attribut SIZE anscheinend bereits vor der if-Abfrage gesetzt ist. Das heisst, ich ändere damit zwar im Falle von s &lt; 1 auf s = 10, aber das bringt mir nichts, weil das SIZE dadurch nicht mehr geändert wird.</p>
<p>Meine Frage also: Kann ich das irgendwie im constructor abfragen und ggf. ändern, BEVOR dss Attribut SIZE gesetzt wird?</p>
<p>Gruss und vielen Dank im Voraus!<br />
Matthias</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1417051</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1417051</guid><dc:creator><![CDATA[haimat]]></dc:creator><pubDate>Sat, 08 Dec 2007 15:01:37 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Sat, 08 Dec 2007 15:10:26 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>die Größe eines Arrays gibt man als std::size_t an. Dieser Typ ist sowieso unsigned.</p>
<p>Möglich wäre aber folgendes:</p>
<pre><code>: SIZE(s &gt; 0 ? s : 10)
</code></pre>
<p>Besser ist aber, im Fall &lt;= 0 einen Fehler zu signalisieren (eine Exception zu werfen).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1417062</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1417062</guid><dc:creator><![CDATA[Freundlich]]></dc:creator><pubDate>Sat, 08 Dec 2007 15:10:26 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Sat, 08 Dec 2007 15:21:25 GMT]]></title><description><![CDATA[<p>Vielen Dank, genau das habe ich gesucht.<br />
Schönen Tag noch!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1417067</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1417067</guid><dc:creator><![CDATA[haimat]]></dc:creator><pubDate>Sat, 08 Dec 2007 15:21:25 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Sat, 08 Dec 2007 19:03:36 GMT]]></title><description><![CDATA[<p>Du möchtest oder musst vermutlich &quot;Data-Encapsulation&quot; zu betreiben! (Lob)</p>
<p>Dann musst du alle Attribute per private schützen und nur über entsprechende public-Methoden den<br />
Zugriff gewähren.</p>
<p>Wenn alle Instanzen deiner Klasse einen SIZE=10 besitzen sollen UND sich dieser nicht mehr ändern soll,<br />
würde ich das Attribut so setzen:</p>
<p>static const int SIZE=10;</p>
<p>die Sache static const Variablen inititieren war glaub ich etwas tricky... macht man die in der Klasse oder ausserhalb der Klasse?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1417234</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1417234</guid><dc:creator><![CDATA[gorgoyle]]></dc:creator><pubDate>Sat, 08 Dec 2007 19:03:36 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Sun, 09 Dec 2007 10:46:19 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">template&lt;typename T&gt;
class container
{
    T* m_array;
    const std::size_t m_size;

public:
    explizit container(std::size_t size) 
        : m_size(size), m_array(new T[size])
    {}
    ~container() { delete [] m_array; }
};
</code></pre>
<p>wobei dann die Frage ist, wofür du überhaupt noch dynamische Arrays nutzt?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1417456</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1417456</guid><dc:creator><![CDATA[*D*Evil]]></dc:creator><pubDate>Sun, 09 Dec 2007 10:46:19 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Sun, 09 Dec 2007 14:28:29 GMT]]></title><description><![CDATA[<p>gorgoyle schrieb:</p>
<blockquote>
<p>die Sache static const Variablen inititieren war glaub ich etwas tricky... macht man die in der Klasse oder ausserhalb der Klasse?</p>
</blockquote>
<p>Mit ganzzahligen Konstanten kannst Du es in der Klasse machen – falls Dein Compiler modern genug ist. Für andere Werte verlagert man die Definition (NICHT aber die Deklaration) nach außerhalb der Klasse.</p>
<pre><code class="language-cpp">struct Test {
    // Deklaration.
    static std::string const cstr;
};

// Definition. KEIN 'static'-Schlüsselwort:
std::string const Test::cstr = &quot;Hallo&quot;;
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1417583</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1417583</guid><dc:creator><![CDATA[Konrad Rudolph]]></dc:creator><pubDate>Sun, 09 Dec 2007 14:28:29 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Sun, 09 Dec 2007 21:31:36 GMT]]></title><description><![CDATA[<blockquote>
<p>Für andere Werte verlagert man die Definition (NICHT aber die Deklaration) nach außerhalb der Klasse.</p>
</blockquote>
<p>Das ist falsch. Auch statische, konstante, integrale Objekte einer Klasse müssen definiert werden. Nur die Initialisierung kann sich in dem Fall in der Klasse befinden, um das Objekt als constant expression nutzen zu können.</p>
<blockquote>
<p>If a static data member is of const integral or const enumeration type, its declaration in the class<br />
definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that<br />
case, the member can appear in integral constant expressions. The member shall still be defined in a name-<br />
space scope if it is used in the program and the namespace scope definition shall not contain an initializer.</p>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/1417839</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1417839</guid><dc:creator><![CDATA[Freundlich]]></dc:creator><pubDate>Sun, 09 Dec 2007 21:31:36 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Mon, 10 Dec 2007 07:40:35 GMT]]></title><description><![CDATA[<p>Freundlich schrieb:</p>
<blockquote>
<blockquote>
<p>Für andere Werte verlagert man die Definition (NICHT aber die Deklaration) nach außerhalb der Klasse.</p>
</blockquote>
<p>Das ist falsch. Auch statische, konstante, integrale Objekte einer Klasse müssen definiert werden. Nur die Initialisierung kann sich in dem Fall in der Klasse befinden, um das Objekt als constant expression nutzen zu können.</p>
</blockquote>
<p>Hmm, Mist. Mein Compiler braucht die Extra-Definition nicht. Wie soll das denn in Code aussehen? So?</p>
<pre><code class="language-cpp">struct test {
    static const int i = 1;
};

const int test::i;
</code></pre>
<p>(Funktioniert. Wunderbar. Aber die letzte Zeile ist im aktuellen GCC und VC++ überflüssig.)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1417912</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1417912</guid><dc:creator><![CDATA[Konrad Rudolph]]></dc:creator><pubDate>Mon, 10 Dec 2007 07:40:35 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Mon, 10 Dec 2007 07:55:44 GMT]]></title><description><![CDATA[<p>(D)Evil schrieb:</p>
<blockquote>
<pre><code class="language-cpp">template&lt;typename T&gt;
class container
{
    T* m_array;
    const std::size_t m_size;

public:
    explizit container(std::size_t size) 
        : m_size(size), m_array(new T[size])
    {}
    ~container() { delete [] m_array; }
};
</code></pre>
</blockquote>
<p>Ohoh, das ist nicht gut. Warum? naja, es könnte jemand auf die Idee kommen, in der Initialisierungsliste an zweiter Stelle</p>
<pre><code class="language-cpp">m_array(new T[size])
</code></pre>
<p>zu schreiben. Na und? <em>And we enter the dark, dusty realms of Undefined Behaviour...</em><br />
Folgendes passiert: Der Compiler initialisiert Klassenmember in der Reihenfolge ihrer Dekaration, und nicht in der Reihenfolge der Initialisierungsliste. Soll heißen, hier würde das <code>m_array(new T[m_size])</code> vor dem <code>m_size(size)</code> ausgeführt, obwohl es dahinter steht. Und da m_size also noch nicht initialisiert ist, ist die Größe des Arrays undefiniert. Von daher sollte man immer die Initiailisierungsliste in gleicher Reihenfolge wie die Deklarationen schreiben, um so subtile Fehler zu vermeiden und sich stundenlanges Bugtracking zu sparen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1417916</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1417916</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Mon, 10 Dec 2007 07:55:44 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Mon, 10 Dec 2007 13:08:18 GMT]]></title><description><![CDATA[<p>Konrad Rudolph schrieb:</p>
<blockquote>
<p>Freundlich schrieb:</p>
<blockquote>
<blockquote>
<p>Für andere Werte verlagert man die Definition (NICHT aber die Deklaration) nach außerhalb der Klasse.</p>
</blockquote>
<p>Das ist falsch. Auch statische, konstante, integrale Objekte einer Klasse müssen definiert werden. Nur die Initialisierung kann sich in dem Fall in der Klasse befinden, um das Objekt als constant expression nutzen zu können.</p>
</blockquote>
<p>Hmm, Mist. Mein Compiler braucht die Extra-Definition nicht. Wie soll das denn in Code aussehen? So?</p>
<pre><code class="language-cpp">struct test {
    static const int i = 1;
};

const int test::i;
</code></pre>
<p>(Funktioniert. Wunderbar. Aber die letzte Zeile ist im aktuellen GCC und VC++ überflüssig.)</p>
</blockquote>
<p>Compiler sind bei solchen Dingen häufig nachsichtig, und Verletzungen der ODR müssen im Allgemeinen nicht diagnostiziert werden. Eine fehlende Definition wird für gewöhnlich frühestens beim Linken erkannt - aber nur dann, wenn tatsächlich eine Referenz auf das jeweilige Symbol existiert, nicht schon dann, wenn eine solche Referenz bloß existieren könnte. Dem Compiler steht es frei, solche Referenzen zu eliminieren, indem z.B. Ausdrücke bereits beim Compilieren ausgewertet werden, in solchen Fällen wird das Auslassen der Definition dann nicht diagnostiziert werden. Umgekehrt ist der Compiler aber nur dort verpflichtet, Ausdrücke beim Compilieren auszuwerten, wenn die Sprache an dieser Stelle einen konstanten Ausdruck erwartet. In allen anderen Fällen ist der Compiler völlig frei - und ein Programm ist nur dann konform, wenn es mit jeder in diesen Grenzen denkbaren Auswertungsentscheidung des Compilers funktioniert. Mithin ergibt sich Folgendes:<br />
1. Eine integrale statische Memberkonstante einer Klasse kann bereits bei ihrer Deklaration initialisiert werden (es ist dann trotzdem nur eine Deklaration).<br />
2. Jede folgende Verwendung des Wertes dieser Konstanten ist ein konstanter Integraler Ausdruck.<br />
3. Eine Definition der Konstanten ist nur dann nicht erforderlich, wenn der Wert in einem Ausdruck verwendet wird, und an der Stelle ein konstanter Ausdruck stehen muss.<br />
Zum Beispiel:</p>
<pre><code class="language-cpp">struct Foo
{
    static const int bar = 42;
    char x[bar]; // erfordert keine Definition
    void f(int y = bar); // erfordert Definition (wenn irgendwo mit Defaultargument aufgerufen)
    void g()
    {
        char* p = new char[bar]; // erfordert Definition
        char* q = new (char[bar]); // erfordert keine Definition
        char (*r)[bar] = new char[10][bar]; // erfordert keine Definition
        bar; // erfordert Definition
        &amp;bar; // erfordert Definition
    }
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1418099</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1418099</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 10 Dec 2007 13:08:18 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Mon, 10 Dec 2007 14:07:09 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/9960">@pumuckl</a>: Hmm naja ok wenn ich m_array(new T[m_size]) da stehen hätte, hättest du recht <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61b.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_tongue"
      title=":P"
      alt="😛"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1418152</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1418152</guid><dc:creator><![CDATA[*D*Evil]]></dc:creator><pubDate>Mon, 10 Dec 2007 14:07:09 GMT</pubDate></item><item><title><![CDATA[Reply to class member initialization on Mon, 10 Dec 2007 17:34:06 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Umgekehrt ist der Compiler aber nur dort verpflichtet, Ausdrücke beim Compilieren auszuwerten, wenn die Sprache an dieser Stelle einen konstanten Ausdruck erwartet.</p>
</blockquote>
<p>Danke für die Erklärung.</p>
<p>Ich habe leider gerade mein Effective C++ nicht zur Hand, erinnere mich aber vage, dass es Meyers auf gleiche Weise falsch gemacht hat wie ich. Daher verzeihe ich mir selbst mal. <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>
]]></description><link>https://www.c-plusplus.net/forum/post/1418279</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1418279</guid><dc:creator><![CDATA[Konrad Rudolph]]></dc:creator><pubDate>Mon, 10 Dec 2007 17:34:06 GMT</pubDate></item></channel></rss>