<?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[Basisklasse mit Membervariable initialisieren]]></title><description><![CDATA[<p>Ich habe folgendes Problem:</p>
<pre><code class="language-cpp">// vorgegeben                                                                   
struct S { int da; bool ta; };
class B {
public:
  B(S *data) { /* ... */ }
};

// von mir geschrieben                                                          
S *create_data(std::string s) { /* komplexe Initialisierung... */ }
class D : public B {
public:
  D(std::string s) : B((data = create_data(s))) {}
private:
  S *data;
};
</code></pre>
<p>Klappt alles wie erwüscht. Nun aber möchte ich Pointer vermeiden und an der Stelle Smartpointer einsetzen.</p>
<p>Mein Wunsch:</p>
<pre><code class="language-cpp">std::tr1::shared_ptr&lt;S&gt; create_data(std::string s) { /* ... */ }
class D : public B {
public:
  D(std::string s) : data(create_data(s)), B(data.get()) {}
private:
  std::tr1::shared_ptr&lt;S&gt; data;
};
</code></pre>
<p>Laut Standard muss die Basisklasse zuerst initialisiert werden, dass <code>data</code> beim Aufruf des Basisklassenkonstruktors undefiniert ist, erstaunt mich daher nicht. Aber so funktioniert das auch nicht:</p>
<pre><code class="language-cpp">std::tr1::shared_ptr&lt;S&gt; create_data(std::string s) { /* ... */ }
class D : public B {
public:
  D(std::string s) : B((data = create_data(s)).get()) {}
private:
  std::tr1::shared_ptr&lt;S&gt; data;
};
</code></pre>
<p>Ich erhalte dabei einen Speicherzugriffsfehler.</p>
<p>Ist es möglich, das auf elegante Art mithilfe von <code>std::tr1::shared_ptr&lt;&gt;</code> zu lösen?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/276402/basisklasse-mit-membervariable-initialisieren</link><generator>RSS for Node</generator><lastBuildDate>Wed, 26 Aug 2026 09:06:19 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/276402.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 01 Nov 2010 18:15:44 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Basisklasse mit Membervariable initialisieren on Mon, 01 Nov 2010 18:15:44 GMT]]></title><description><![CDATA[<p>Ich habe folgendes Problem:</p>
<pre><code class="language-cpp">// vorgegeben                                                                   
struct S { int da; bool ta; };
class B {
public:
  B(S *data) { /* ... */ }
};

// von mir geschrieben                                                          
S *create_data(std::string s) { /* komplexe Initialisierung... */ }
class D : public B {
public:
  D(std::string s) : B((data = create_data(s))) {}
private:
  S *data;
};
</code></pre>
<p>Klappt alles wie erwüscht. Nun aber möchte ich Pointer vermeiden und an der Stelle Smartpointer einsetzen.</p>
<p>Mein Wunsch:</p>
<pre><code class="language-cpp">std::tr1::shared_ptr&lt;S&gt; create_data(std::string s) { /* ... */ }
class D : public B {
public:
  D(std::string s) : data(create_data(s)), B(data.get()) {}
private:
  std::tr1::shared_ptr&lt;S&gt; data;
};
</code></pre>
<p>Laut Standard muss die Basisklasse zuerst initialisiert werden, dass <code>data</code> beim Aufruf des Basisklassenkonstruktors undefiniert ist, erstaunt mich daher nicht. Aber so funktioniert das auch nicht:</p>
<pre><code class="language-cpp">std::tr1::shared_ptr&lt;S&gt; create_data(std::string s) { /* ... */ }
class D : public B {
public:
  D(std::string s) : B((data = create_data(s)).get()) {}
private:
  std::tr1::shared_ptr&lt;S&gt; data;
};
</code></pre>
<p>Ich erhalte dabei einen Speicherzugriffsfehler.</p>
<p>Ist es möglich, das auf elegante Art mithilfe von <code>std::tr1::shared_ptr&lt;&gt;</code> zu lösen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1973735</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1973735</guid><dc:creator><![CDATA[initprob]]></dc:creator><pubDate>Mon, 01 Nov 2010 18:15:44 GMT</pubDate></item><item><title><![CDATA[Reply to Basisklasse mit Membervariable initialisieren on Tue, 02 Nov 2010 10:55:25 GMT]]></title><description><![CDATA[<p>Benutze wenn, dann überall shared_ptr. Auch in B</p>
<pre><code class="language-cpp">class B {
public:
  B(const shared_ptr&lt;S&gt; data) { /* ... */ }
};
</code></pre>
<p>Dafür ist der <strong>shared</strong>_ptr ja da.</p>
<pre><code class="language-cpp">class D : public B
{
public:
  D(shared_ptr&lt;S&gt; s) : B(s), s_(s) {}
  static D FromText(const std::string&amp; s)
  {
     return D(create_data(s));
  }
private:
  shared_ptr&lt;S&gt; s_;
};
</code></pre>
<p>Was aber ist überhaupt der Grund dafür, das S über einen Zeiger zu halten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1974018</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1974018</guid><dc:creator><![CDATA[brotbernd]]></dc:creator><pubDate>Tue, 02 Nov 2010 10:55:25 GMT</pubDate></item><item><title><![CDATA[Reply to Basisklasse mit Membervariable initialisieren on Tue, 02 Nov 2010 16:43:10 GMT]]></title><description><![CDATA[<p><code>B</code> kann ich leider nicht ändern, weil ich von <code>std::iostream</code> erbe und leider benötigt das einen Zeiger auf einen <code>std::streambuf</code> .<br />
den <code>std::streambuf</code> kann und will ich nicht kopierbar machen, was der Grund für die Zeigerhaltung ist.</p>
<p>Beim Nachschauen, wie <code>boost::stream</code> das macht, bin ich auf das <a href="http://www.boost.org/doc/libs/1_40_0/libs/utility/base_from_member.html" rel="nofollow">Boost: Base-from-Member Idiom</a> gestossen. Der Name &quot; <code>member</code> &quot; sieht zwar etwas komisch aus, aber damit bin ich jetzt zufrieden. Scheinbar gibt es keine bessere Lösung für mein Problem.</p>
<p>Der shared_ptr ist wirklich fehl am Platz, da hast du Recht. Mit den C++0x-Erweiterungen bin ich auf folgende, mich zufriedenstellende Lösung gekommen:</p>
<pre><code class="language-cpp">S *create_data(std::string s) { /* ... */ }
class D : private boost::base_from_member&lt;std::unique_ptr&lt;S&gt;&gt;, public B {
public:
  D(std::string s) : boost::base_from_member&lt;std::unique_ptr&lt;S&gt;&gt;(create_data(s)), B(member.get()) {}
};
</code></pre>
<p>Ohne C++0x muss ich wohl den <code>boost::scoped_ptr</code> verwenden.</p>
<p>Vielen Dank für deine Hilfe!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1974248</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1974248</guid><dc:creator><![CDATA[initprob]]></dc:creator><pubDate>Tue, 02 Nov 2010 16:43:10 GMT</pubDate></item></channel></rss>