<?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[Operator-Overloadding und Streams Verständnisproblem]]></title><description><![CDATA[<p>Hallo.</p>
<p>ich habe mir eine Klasse geschrieben die in eine Datei und gleichzeitig auf std::cout loggen kann. Da ich mich mit Streams noch nie wirklich intensiv beschäftigt habe, habe ich meine Schwierigkeiten etwas zu verstehen.</p>
<p>Hier der komplette Code:</p>
<pre><code class="language-cpp">class logger
{
public:
    logger()
    {
        ofs_.open(&quot;log.log&quot;, std::ios::app);
    }

    ~logger()
    {
        ofs_.close();
    }

    template&lt;typename T&gt;
    logger&amp; operator &lt;&lt;(const T &amp;data)
    {
        ofs_ &lt;&lt; data;
        std::cout &lt;&lt; data;
        return *this;
    }

    typedef std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt; cout_type;
    typedef cout_type&amp; (*default_endline)(cout_type&amp;);

    logger&amp; operator &lt;&lt;(default_endline manip)
    {
        manip(ofs_);
        manip(std::cout);
        return *this;
    }
private:
    std::ofstream ofs_;
};
</code></pre>
<p>Mein Problem beginnt ab Zeile 22.</p>
<pre><code class="language-cpp">typedef std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt; cout_type;
typedef cout_type&amp; (*default_endline)(cout_type&amp;);

logger&amp; operator &lt;&lt;(default_endline manip)
{
    manip(ofs_);
    manip(std::cout);
    return *this;
}
</code></pre>
<p>Der erste Typedef ist klar ich erstelle mir einen Alias für den type <em>std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;</em> was ja auch std::cout und std::endl; entspricht. Soweit so gut.<br />
Aber was ist das hier: *typedef cout_type&amp; (<em>default_endline)(cout_type&amp;);</em></p>
<p>Nur dadurch ist so was möglich:</p>
<pre><code class="language-cpp">logger l;
l &lt;&lt; &quot;test &quot; &lt;&lt; 123 &lt;&lt; std::endl;
</code></pre>
<p>Es wird also nur für std::endl benötigt. Was ich doch sehr verwirrend finde, da ich ja schon eine Template Funktion habe die jeden Datentyp entgegen nehmen kann, also warum auch nicht diesen.</p>
<p>Qt kann das (glaube ich), das habe ich mal in einem Beispiel gesehen.</p>
<pre><code class="language-cpp">#include &lt;qdebug&gt;
qDebug() &lt;&lt; &quot;Hallo Welt!&quot; &lt;&lt; std::endl;
</code></pre>
<p>Ich will das auch haben <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="🙂"
    /> Die schreibweise ist super.</p>
<p>Über ein paar Tipps wäre ich dankbar.</p>
<p>Grüße.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/307837/operator-overloadding-und-streams-verständnisproblem</link><generator>RSS for Node</generator><lastBuildDate>Thu, 06 Aug 2026 09:31:12 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/307837.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 06 Sep 2012 13:10:48 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Operator-Overloadding und Streams Verständnisproblem on Thu, 06 Sep 2012 13:10:48 GMT]]></title><description><![CDATA[<p>Hallo.</p>
<p>ich habe mir eine Klasse geschrieben die in eine Datei und gleichzeitig auf std::cout loggen kann. Da ich mich mit Streams noch nie wirklich intensiv beschäftigt habe, habe ich meine Schwierigkeiten etwas zu verstehen.</p>
<p>Hier der komplette Code:</p>
<pre><code class="language-cpp">class logger
{
public:
    logger()
    {
        ofs_.open(&quot;log.log&quot;, std::ios::app);
    }

    ~logger()
    {
        ofs_.close();
    }

    template&lt;typename T&gt;
    logger&amp; operator &lt;&lt;(const T &amp;data)
    {
        ofs_ &lt;&lt; data;
        std::cout &lt;&lt; data;
        return *this;
    }

    typedef std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt; cout_type;
    typedef cout_type&amp; (*default_endline)(cout_type&amp;);

    logger&amp; operator &lt;&lt;(default_endline manip)
    {
        manip(ofs_);
        manip(std::cout);
        return *this;
    }
private:
    std::ofstream ofs_;
};
</code></pre>
<p>Mein Problem beginnt ab Zeile 22.</p>
<pre><code class="language-cpp">typedef std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt; cout_type;
typedef cout_type&amp; (*default_endline)(cout_type&amp;);

logger&amp; operator &lt;&lt;(default_endline manip)
{
    manip(ofs_);
    manip(std::cout);
    return *this;
}
</code></pre>
<p>Der erste Typedef ist klar ich erstelle mir einen Alias für den type <em>std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;</em> was ja auch std::cout und std::endl; entspricht. Soweit so gut.<br />
Aber was ist das hier: *typedef cout_type&amp; (<em>default_endline)(cout_type&amp;);</em></p>
<p>Nur dadurch ist so was möglich:</p>
<pre><code class="language-cpp">logger l;
l &lt;&lt; &quot;test &quot; &lt;&lt; 123 &lt;&lt; std::endl;
</code></pre>
<p>Es wird also nur für std::endl benötigt. Was ich doch sehr verwirrend finde, da ich ja schon eine Template Funktion habe die jeden Datentyp entgegen nehmen kann, also warum auch nicht diesen.</p>
<p>Qt kann das (glaube ich), das habe ich mal in einem Beispiel gesehen.</p>
<pre><code class="language-cpp">#include &lt;qdebug&gt;
qDebug() &lt;&lt; &quot;Hallo Welt!&quot; &lt;&lt; std::endl;
</code></pre>
<p>Ich will das auch haben <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="🙂"
    /> Die schreibweise ist super.</p>
<p>Über ein paar Tipps wäre ich dankbar.</p>
<p>Grüße.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2249098</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249098</guid><dc:creator><![CDATA[create_problem]]></dc:creator><pubDate>Thu, 06 Sep 2012 13:10:48 GMT</pubDate></item><item><title><![CDATA[Reply to Operator-Overloadding und Streams Verständnisproblem on Thu, 06 Sep 2012 13:17:08 GMT]]></title><description><![CDATA[<p>// Edit<br />
Sorry habe einige zeilen Text vergessen, den letzten Teil recht unvertändlich macht. Ich kann leider meinen Beitrag nicht mehr ändern.</p>
<p>Dann hätte ich noch eine andere Frage zur Verwendung.<br />
Ich würde meine Klasse gerne so verwenden, wie man es mit std::cout auch macht, ohne manuell ein Objekt der Klasse zu erzeugen. Kann mir jemand sagen wie man das Realisiert? Macros wären auch ok.</p>
<p>Es wird also nur für std::endl benötigt. Was ich doch sehr verwirrend finde, da ich ja schon eine Template Funktion habe die jeden Datentyp entgegen nehmen kann, also warum auch nicht diesen.</p>
<p>Qt kann das (glaube ich), das habe ich mal in einem Beispiel gesehen.</p>
<pre><code class="language-cpp">#include &lt;qdebug&gt;
qDebug() &lt;&lt; &quot;Hallo Welt!&quot; &lt;&lt; std::endl;
</code></pre>
<p>Ich will das auch haben <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="🙂"
    /> Die schreibweise ist super.</p>
<p>Sorry für das kleine Durcheinander, werde mir bei Gelegenheit einen Account anlegen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2249099</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249099</guid><dc:creator><![CDATA[create_problem]]></dc:creator><pubDate>Thu, 06 Sep 2012 13:17:08 GMT</pubDate></item><item><title><![CDATA[Reply to Operator-Overloadding und Streams Verständnisproblem on Thu, 06 Sep 2012 15:28:28 GMT]]></title><description><![CDATA[<p>create_problem schrieb:</p>
<blockquote>
<p>Aber was ist das hier: *typedef cout_type&amp; (<em>default_endline)(cout_type&amp;);</em></p>
</blockquote>
<p>Allgemein: <code>default_endline</code> ist ein Zeiger auf eine Funktion, die einen Parameter <code>cout_type&amp;</code> hat und <code>cout_type&amp;</code> zurückgibt.<br />
Praktisch: Da das Ganze mit <code>typedef</code> gemacht wird, ist <code>default_endline</code> nun ein Typ für solch einen Zeiger. Dann kannst du das machen:</p>
<pre><code class="language-cpp">cout_type&amp; fkt(cout_type&amp; ct)
{
}
default_endline p = &amp;fkt; // Der Zeiger p zeigt auf die Funktion fkt.
</code></pre>
<p>Offiziell schaut das eigentlich so aus:</p>
<pre><code class="language-cpp">typedef std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt; ostream;
</code></pre>
<p>Du hast nun inoffiziell das gemacht:</p>
<pre><code class="language-cpp">typedef std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt; cout_type;
</code></pre>
<p>Fazit: <code>cout_type</code> ist <code>ostream</code> .</p>
<p>create_problem schrieb:</p>
<blockquote>
<p>Es wird also nur für std::endl benötigt.</p>
</blockquote>
<p>Ja. Ich hab mal anschaulicher gemacht:</p>
<pre><code class="language-cpp">class logger
{
    public:
		logger&amp; operator &lt;&lt;(default_endline manip)
		{
			manip(ofs_);
			manip(std::cout);
			return *this;
		}
};

std::ostream&amp; neue_zeile(std::ostream&amp; os)
{
	os &lt;&lt; '\n';
	return os;
}

int main()
{
	logger l;
	l &lt;&lt; neue_zeile;
}
</code></pre>
<ol>
<li><code>l &lt;&lt; neue_zeile</code> ist dasselbe wie <code>l.operator&lt;&lt;(neue_zeile)</code> .</li>
<li><code>neue_zeile</code> ist eine Funktion, die ein <code>ostream</code> Argument erwartet und ein <code>ostream</code> zurückgibt. Wir erinnern uns, dass dein <code>cout_type</code> ja <code>ostream</code> ist.<br />
3. Dein <code>operator&lt;&lt;(default_endline manip)</code> will als Argument eine Funktion, die ein <code>ostream</code> Argument erwartet und ein <code>ostream</code> zurückgibt. <code>neue_zeile</code> erfüllt diese Anforderungen.</li>
<li><code>manip</code> ist dann ein Zeiger auf die Funktion <code>neue_zeile</code> .</li>
<li><code>manip(std::cout)</code> ruft dann schlußendlich die Funktion <code>neue_zeile</code> auf.</li>
</ol>
<p>Achja, und der Grund, wieso nicht</p>
<pre><code class="language-cpp">template&lt;typename T&gt;
    logger&amp; operator &lt;&lt;(const T &amp;data)
</code></pre>
<p>sondern</p>
<pre><code class="language-cpp">logger&amp; operator &lt;&lt;(default_endline manip)
</code></pre>
<p>genommen wird, ist einfach, weil letzteres spezieller ist, es ist einfach ein besserer match.</p>
<p>Ich hoffe, das du es nun verstanden hast. <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/2249155</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249155</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 06 Sep 2012 15:28:28 GMT</pubDate></item><item><title><![CDATA[Reply to Operator-Overloadding und Streams Verständnisproblem on Thu, 06 Sep 2012 17:10:16 GMT]]></title><description><![CDATA[<p>Hallo.</p>
<p>Danke für deine Antwort, war sehr aufschlussreich. Ich habe es nun verstanden und auch festgestellt das ich auf den Gebiet Nachholbedarf habe.</p>
<p>Grüße.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2249211</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2249211</guid><dc:creator><![CDATA[create_problem]]></dc:creator><pubDate>Thu, 06 Sep 2012 17:10:16 GMT</pubDate></item></channel></rss>