<?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[Programm mit Funktionen --&amp;gt; zu Klasse machen]]></title><description><![CDATA[<p>Abend,</p>
<p>Folgende Aufgabe habe ich gelöst und möchte diese nun in eine Klasse verpacken ( zur Übung):</p>
<blockquote>
<p>Eine Datei MESS.DAT im Stammverzeichnis der Festplatte C: enthält genau 100 Messwerte vom double-Typ. Die Messwerte sollen aus der Datei in ein Feld eingelesen werden. Mittels dreier Funk-tionen, die Sie definieren sollen, werden a) der Mittelwert, b) das Maximum und c) das Minimum der Messwerte bestimmt und in eine Datei ERGEBNIS.DAT im Stammverzeichnis der Festplatte C: ab-gelegt.</p>
</blockquote>
<p>Mit Unterfunktionen realisiert ( ist Funktionsfähig)</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;string&gt;
#include &lt;algorithm&gt;
#define ANZAHL 10

using namespace std;

//Funktionsdeklarationen
int einlesen(string quell_datei, double* messwerte);
double mittelwert(double* messwerte);
double maximum(double *messwerte);
double minimum(double *messwerte);
void ausgabe(string ausgabe_datei, double* messwerte);

int main()
	{
		//Dateien
		string quell_datei = &quot;C:\\MESS.DAT&quot;;
		string ausgabe_datei = &quot;C:\\ERGEBNIS.DAT&quot;;
		double* messwerte = new double [ANZAHL];

		//File input
		einlesen(quell_datei,messwerte);

		//File output
		ausgabe(ausgabe_datei,messwerte);
	}

int einlesen(string quell_datei, double* messwerte)
	{
		ifstream input;
		input.open(quell_datei.c_str(), ios_base::in);

		if (!input)
			{
				cout &lt;&lt; &quot;Datei öffnen fehlgeschlagen!&quot;;
				return -1;
			}

		for (int i = 0; i &lt; ANZAHL; i++)
			{
				input &gt;&gt; messwerte[i];
			}

		input.close();
	}
void ausgabe(string ausgabe_datei, double* messwerte)
	{
		ofstream output;
		output.open(ausgabe_datei.c_str(), ios_base::out);

		if (!output)
			{
				cout &lt;&lt; &quot;Datei erstellen fehlgeschlagen!&quot;;
			}

		output &lt;&lt; &quot;Mittelwert der &quot; &lt;&lt; ANZAHL &lt;&lt; &quot; Werte lautet: &quot; &lt;&lt; mittelwert(messwerte);;
		output &lt;&lt; &quot;\nMaximum der &quot; &lt;&lt; ANZAHL &lt;&lt; &quot; Werte lautet: &quot; &lt;&lt; maximum(messwerte);;
		output &lt;&lt; &quot;\nMinimum der &quot; &lt;&lt; ANZAHL &lt;&lt; &quot; Werte lautet: &quot; &lt;&lt; minimum(messwerte);;

		output.close();
	}

double mittelwert(double* messwerte)
	{
		double mittelwert=0;
		for (int j=0; j &lt; ANZAHL; j++)
			{
				mittelwert += messwerte[j];
			}

		return (mittelwert/ANZAHL);
	}
double maximum(double* messwerte)
	{
		double maximum = *max_element(messwerte, messwerte+ANZAHL);

		return maximum;
	}
double minimum(double* messwerte)
	{
		double minimum = *min_element(messwerte, messwerte+ANZAHL);

		return minimum;
	}
</code></pre>
<p>**So und ab hier ist mein Lösungsansatz um das ganze mit einer Klasse zu realisieren:</p>
<p>mit dem Ausgabe Operator stimmt bei dem Programm scheibar was noch nicht:</p>
<blockquote>
<p>error C2804: Binärer Operator '&lt;&lt;' hat zu viele Parameter</p>
</blockquote>
<p>**</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;string&gt;
#include &lt;algorithm&gt;
#define ANZAHL 10

using namespace std;

class Detail
	{
		private:
				string inFile;
				string outFile;
		public:

				Detail(); //Default-Konstruktor
				Detail(string inFile, string outFile); //Parameter-Konstruktor

				//Getter
				int auslesen(string in,double* messwerte)const;

				double mittelwert(double* messwerte)const;
				double maximum(double* messwerte)const;
				double minimum(double* messwerte)const;

				//Setter
				friend ofstream&amp; operator &lt;&lt; (ofstream&amp; outFile,Detail const&amp; wert, double* messwerte);
	};

Detail::Detail()
	{
		inFile= &quot;C:\\MESS.DAT&quot;;
		outFile= &quot;C:\\ERGEBNIS.DAT&quot;;
	}

Detail::Detail(string inFile, string outFile)
	{
		this-&gt;inFile= inFile;
		this-&gt;outFile= outFile;
	}

int Detail::auslesen(string in,double* messwerte)const
	{
		ifstream input;
		input.open(in.c_str(), ios_base::in);

		if (!input)
			{
				cout &lt;&lt; &quot;Datei öffnen fehlgeschlagen!&quot;;
				return -1;
			}

		for (int i = 0; i &lt; ANZAHL; i++)
			{
				input &gt;&gt; messwerte[i];
			}

		input.close();
	}

double Detail::mittelwert(double* messwerte)const
	{
		double mittelwert=0;
		for (int j=0; j &lt; ANZAHL; j++)
			{
				mittelwert += messwerte[j];
			}

		return (mittelwert/ANZAHL);
	}
double Detail::maximum(double* messwerte)const
{
	double maximum = *max_element(messwerte, messwerte+ANZAHL);

	return maximum;
}
double Detail::minimum(double* messwerte)const
	{
		double minimum = *min_element(messwerte, messwerte+ANZAHL);

		return minimum;
	}

int main()
{
Detail Standard ();
cout &lt;&lt; Standard;
}

ofstream&amp; operator &lt;&lt; (ofstream&amp; outFile,Detail const&amp; wert, double* messwerte)
	{
		return (outFile &lt;&lt; &quot;Der Mittelwert ist: &quot; &lt;&lt; wert.mittelwert(messwerte) &lt;&lt; &quot;\nDer Maximalwert ist: &quot; &lt;&lt; wert.maximum(messwerte) &lt;&lt; &quot;\nDer Minimalwert ist: &quot; &lt;&lt; wert.minimum(messwerte));
	}
</code></pre>
<p>Hat jemand ne ahnung was der Fehler ist?</p>
<p>vielen dank im voraus<br />
mfg fraggelfragger</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/201676/programm-mit-funktionen-gt-zu-klasse-machen</link><generator>RSS for Node</generator><lastBuildDate>Tue, 06 Oct 2026 05:02:47 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/201676.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 02 Jan 2008 22:29:25 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Programm mit Funktionen --&amp;gt; zu Klasse machen on Wed, 02 Jan 2008 22:31:05 GMT]]></title><description><![CDATA[<p>Abend,</p>
<p>Folgende Aufgabe habe ich gelöst und möchte diese nun in eine Klasse verpacken ( zur Übung):</p>
<blockquote>
<p>Eine Datei MESS.DAT im Stammverzeichnis der Festplatte C: enthält genau 100 Messwerte vom double-Typ. Die Messwerte sollen aus der Datei in ein Feld eingelesen werden. Mittels dreier Funk-tionen, die Sie definieren sollen, werden a) der Mittelwert, b) das Maximum und c) das Minimum der Messwerte bestimmt und in eine Datei ERGEBNIS.DAT im Stammverzeichnis der Festplatte C: ab-gelegt.</p>
</blockquote>
<p>Mit Unterfunktionen realisiert ( ist Funktionsfähig)</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;string&gt;
#include &lt;algorithm&gt;
#define ANZAHL 10

using namespace std;

//Funktionsdeklarationen
int einlesen(string quell_datei, double* messwerte);
double mittelwert(double* messwerte);
double maximum(double *messwerte);
double minimum(double *messwerte);
void ausgabe(string ausgabe_datei, double* messwerte);

int main()
	{
		//Dateien
		string quell_datei = &quot;C:\\MESS.DAT&quot;;
		string ausgabe_datei = &quot;C:\\ERGEBNIS.DAT&quot;;
		double* messwerte = new double [ANZAHL];

		//File input
		einlesen(quell_datei,messwerte);

		//File output
		ausgabe(ausgabe_datei,messwerte);
	}

int einlesen(string quell_datei, double* messwerte)
	{
		ifstream input;
		input.open(quell_datei.c_str(), ios_base::in);

		if (!input)
			{
				cout &lt;&lt; &quot;Datei öffnen fehlgeschlagen!&quot;;
				return -1;
			}

		for (int i = 0; i &lt; ANZAHL; i++)
			{
				input &gt;&gt; messwerte[i];
			}

		input.close();
	}
void ausgabe(string ausgabe_datei, double* messwerte)
	{
		ofstream output;
		output.open(ausgabe_datei.c_str(), ios_base::out);

		if (!output)
			{
				cout &lt;&lt; &quot;Datei erstellen fehlgeschlagen!&quot;;
			}

		output &lt;&lt; &quot;Mittelwert der &quot; &lt;&lt; ANZAHL &lt;&lt; &quot; Werte lautet: &quot; &lt;&lt; mittelwert(messwerte);;
		output &lt;&lt; &quot;\nMaximum der &quot; &lt;&lt; ANZAHL &lt;&lt; &quot; Werte lautet: &quot; &lt;&lt; maximum(messwerte);;
		output &lt;&lt; &quot;\nMinimum der &quot; &lt;&lt; ANZAHL &lt;&lt; &quot; Werte lautet: &quot; &lt;&lt; minimum(messwerte);;

		output.close();
	}

double mittelwert(double* messwerte)
	{
		double mittelwert=0;
		for (int j=0; j &lt; ANZAHL; j++)
			{
				mittelwert += messwerte[j];
			}

		return (mittelwert/ANZAHL);
	}
double maximum(double* messwerte)
	{
		double maximum = *max_element(messwerte, messwerte+ANZAHL);

		return maximum;
	}
double minimum(double* messwerte)
	{
		double minimum = *min_element(messwerte, messwerte+ANZAHL);

		return minimum;
	}
</code></pre>
<p>**So und ab hier ist mein Lösungsansatz um das ganze mit einer Klasse zu realisieren:</p>
<p>mit dem Ausgabe Operator stimmt bei dem Programm scheibar was noch nicht:</p>
<blockquote>
<p>error C2804: Binärer Operator '&lt;&lt;' hat zu viele Parameter</p>
</blockquote>
<p>**</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;string&gt;
#include &lt;algorithm&gt;
#define ANZAHL 10

using namespace std;

class Detail
	{
		private:
				string inFile;
				string outFile;
		public:

				Detail(); //Default-Konstruktor
				Detail(string inFile, string outFile); //Parameter-Konstruktor

				//Getter
				int auslesen(string in,double* messwerte)const;

				double mittelwert(double* messwerte)const;
				double maximum(double* messwerte)const;
				double minimum(double* messwerte)const;

				//Setter
				friend ofstream&amp; operator &lt;&lt; (ofstream&amp; outFile,Detail const&amp; wert, double* messwerte);
	};

Detail::Detail()
	{
		inFile= &quot;C:\\MESS.DAT&quot;;
		outFile= &quot;C:\\ERGEBNIS.DAT&quot;;
	}

Detail::Detail(string inFile, string outFile)
	{
		this-&gt;inFile= inFile;
		this-&gt;outFile= outFile;
	}

int Detail::auslesen(string in,double* messwerte)const
	{
		ifstream input;
		input.open(in.c_str(), ios_base::in);

		if (!input)
			{
				cout &lt;&lt; &quot;Datei öffnen fehlgeschlagen!&quot;;
				return -1;
			}

		for (int i = 0; i &lt; ANZAHL; i++)
			{
				input &gt;&gt; messwerte[i];
			}

		input.close();
	}

double Detail::mittelwert(double* messwerte)const
	{
		double mittelwert=0;
		for (int j=0; j &lt; ANZAHL; j++)
			{
				mittelwert += messwerte[j];
			}

		return (mittelwert/ANZAHL);
	}
double Detail::maximum(double* messwerte)const
{
	double maximum = *max_element(messwerte, messwerte+ANZAHL);

	return maximum;
}
double Detail::minimum(double* messwerte)const
	{
		double minimum = *min_element(messwerte, messwerte+ANZAHL);

		return minimum;
	}

int main()
{
Detail Standard ();
cout &lt;&lt; Standard;
}

ofstream&amp; operator &lt;&lt; (ofstream&amp; outFile,Detail const&amp; wert, double* messwerte)
	{
		return (outFile &lt;&lt; &quot;Der Mittelwert ist: &quot; &lt;&lt; wert.mittelwert(messwerte) &lt;&lt; &quot;\nDer Maximalwert ist: &quot; &lt;&lt; wert.maximum(messwerte) &lt;&lt; &quot;\nDer Minimalwert ist: &quot; &lt;&lt; wert.minimum(messwerte));
	}
</code></pre>
<p>Hat jemand ne ahnung was der Fehler ist?</p>
<p>vielen dank im voraus<br />
mfg fraggelfragger</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1429616</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1429616</guid><dc:creator><![CDATA[fraggelfragger]]></dc:creator><pubDate>Wed, 02 Jan 2008 22:31:05 GMT</pubDate></item><item><title><![CDATA[Reply to Programm mit Funktionen --&amp;gt; zu Klasse machen on Wed, 02 Jan 2008 22:44:05 GMT]]></title><description><![CDATA[<p>Ohne den Code großartig durschauen zu wollen:</p>
<p>Der Operator &lt;&lt; bekommt als Parameter einmal den ostream, und dazu noch deine Klasse für die du ihn schreibst. Was du da noch übergeben willst ist mir schleierhaft.</p>
<p>In deiner main übergibst du ihm ja auch nur eine Instanz deiner Klasse.</p>
<p>Ps:<br />
Wenn ich mir den Code so anschaue, passt ein Operator&lt;&lt; nicht gerade zu deiner Klasse.<br />
Im Grunde ist sie ja nur eine Ansammlung von Funktionen sowie zwei Strings, durch die du Werte einlesen kannst.</p>
<p>Mein Vorschlag: Speichere in deiner Klasse noch ein Array von Messwerten, und speichere so die eingelesenen Daten in deiner Klasse.<br />
Dann kannst du diese auch im operator&lt;&lt; ausgeben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1429625</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1429625</guid><dc:creator><![CDATA[The-Kenny]]></dc:creator><pubDate>Wed, 02 Jan 2008 22:44:05 GMT</pubDate></item><item><title><![CDATA[Reply to Programm mit Funktionen --&amp;gt; zu Klasse machen on Wed, 02 Jan 2008 23:54:16 GMT]]></title><description><![CDATA[<p>Ach du Scheiße ...</p>
<p>Also von vorne:<br />
Als erstes musst du dir überlegen, was die Klasse soll. Sie soll deine Daten verwalten. Also muss sie die Daten kennen.<br />
Daraus ergibt sich:</p>
<pre><code class="language-cpp">class measurements
{
	std::vector&lt;double&gt; m_data;
};
</code></pre>
<p>m_data ist also private (bei class default, bei struct wäre es public).<br />
Dann willst du die Daten aus einem Stream lesen können. Welcher das ist, soll dir doch egal sein? So lange du mit den Funktionen von std::ostream auskommst, musst du dich doch nicht auf einen bestimmten beschränken.<br />
Also musst du den Stream-Operator &gt;&gt; überladen. Das selbe zum Ausgeben!</p>
<pre><code class="language-cpp">class measurements
{
	std::vector&lt;double&gt; m_data;

public:
	friend std::istream&amp; operator&gt;&gt;(std::istream&amp; in, measurements&amp; data);
	friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out, measurements const&amp; data);
};
</code></pre>
<p>Dann optimieren wir mal deinen Code zum einlesen:</p>
<pre><code class="language-cpp">int Detail::auslesen(string in,double* messwerte)const
    {
        ifstream input;
        input.open(in.c_str(), ios_base::in);

        if (!input)
            {
                cout &lt;&lt; &quot;Datei öffnen fehlgeschlagen!&quot;;
                return -1;
            }

        for (int i = 0; i &lt; ANZAHL; i++)
            {
                input &gt;&gt; messwerte[i];
            }

        input.close();
    }
</code></pre>
<p>Nun als erstes hat std::ifstream einen Konstruktor, sodass du nicht zusätzlich die Funktion open aufrufen musst. Dann ist bei std::<strong>i</strong>fstream sowieso klar, das es std::ios_base::in ist <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="😉"
    /><br />
Wenn du von 0 bis &gt;0 hochzählst, kannst du einen unsignieren Typen nehmen, da es eh positive Zahlen sind <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="😉"
    /><br />
Zu guter letzt kannst du den Aufruf von close dir sparen, da dieser im Destruktor (beim verlassen des Scopes(in dem Fall der Funktion)) aufgerufen wird.</p>
<pre><code class="language-cpp">int Detail::auslesen(string in, double* messwerte) const
{
	std::ifstream input(in.c_str());

	if (!input)
	{
		cout &lt;&lt; &quot;Datei öffnen fehlgeschlagen!&quot;;
		return -1;
	}

	for (unsigned int i = 0; i &lt; ANZAHL; i++)
		input &gt;&gt; messwerte[i];
}
</code></pre>
<p>nun fällt auf, das du auch einen Wert zurück geben musst, wenn die Funktion erfolgreich war! Und evtl. kommst du auch mit true und false hin. Achja und in solltest du besser als const Reference übergeben. Aber das interessiert uns nun nicht weiter, da wir das nicht brauchen, wenn wir operator &gt;&gt; nutzen, da dort weder eine Möglichkeit gegeben ist einen Wert zurück zu geben noch einen String diesem zu übergeben <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="😉"
    /> Aber wir bekommen einen std::istream! Und diese hat das fail &amp; bad - bit, das wir jeweils setzen können, wenn etwas schief geht!</p>
<p>Achja, ein Problem haben wir noch. Wie viele Werte sind den nun in der Datei? Das interessiert uns nicht! Wenn nichts mehr drin steht, schlägt input &gt;&gt; messwerte[i]; fehl!</p>
<pre><code class="language-cpp">friend std::istream&amp; operator&gt;&gt;(std::istream&amp; in, measurements&amp; data)
{
	double tmp(0.0);
	while (in &gt;&gt; tmp) m_data.push_back(tmp);
	return in;
}
</code></pre>
<p>wäre doch gut! Wir lesen ein und gucken ob alles in ordnung war (while (in &gt;&gt; tmp)) und wenn jahr packen wir es zu unseren daten (m_data.push_back(tmp)).</p>
<p>Nun das selbe zum Ausgeben!</p>
<pre><code class="language-cpp">friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out, measurements const&amp; data)
{
	return (out &lt;&lt; &quot;Der Mittelwert ist: &quot; &lt;&lt; data.midpoint() &lt;&lt; &quot;\nDer Maximalwert ist: &quot; &lt;&lt; data.max() &lt;&lt; &quot;\nDer Minimalwert ist: &quot; &lt;&lt; data.min());
}
</code></pre>
<p>So.</p>
<p>Jetzt noch deine 3 Funktionen und schon fertig:</p>
<pre><code class="language-cpp">double measurements::midpoint() const
{
    double tmp(0);
    for (std::size_t i(0); i &lt; m_data.size(); ++i)
        tmp += m_data[i];

    return tmp / m_data.size();
}
</code></pre>
<p>Nun kann man hier das ein wenig kürzen, in dem man mit std::plus&lt;double&gt; und std::transform arbeitet, aber das wäre difinitiv über dem Niveau der restlichen Klasse <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>
<pre><code class="language-cpp">double measurements::max() const
{
    return *std::max_element(m_data.begin(), m_data.end());
}
</code></pre>
<pre><code class="language-cpp">double measurements::min() const
{
    return *std::min_element(m_data.begin(), m_data.end());
}
</code></pre>
<p>. Soweit wäre das alles:<br />
<strong>measurements.hpp</strong></p>
<pre><code class="language-cpp">#if !defined (MEASUREMENTS_HPP__INCLUDED)
#define MEASUREMENTS_HPP__INCLUDED

#if (_MSC_VER &gt;= 1300)
#pragma once
#endif // (_MSC_VER &gt;= 1300)

#include &lt;vector&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;

class measurements
{
	std::vector&lt;double&gt; m_data;

public:
	friend std::istream&amp; operator&gt;&gt;(std::istream&amp; in, measurements&amp; data)
	{
		double tmp(0.0);
		while (in &gt;&gt; tmp) m_data.push_back(tmp);
		return in;
	}
	friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out, measurements const&amp; data)
	{ return (out &lt;&lt; &quot;Der Mittelwert ist: &quot; &lt;&lt; data.midpoint() &lt;&lt; &quot;\nDer Maximalwert ist: &quot; &lt;&lt; data.max() &lt;&lt; &quot;\nDer Minimalwert ist: &quot; &lt;&lt; data.min()); }

public:
	double measurements::max() const
	{ return *std::max_element(m_data.begin(), m_data.end()); }
	double measurements::min() const
	{ return *std::min_element(m_data.begin(), m_data.end()); }
	double measurements::midpoint() const
	{
		double tmp(0);
		for (std::size_t i(0); i &lt; m_data.size(); ++i)
			tmp += m_data[i];
		return tmp / m_data.size();
	}
};

#endif // MEASUREMENTS_HPP__INCLUDED
</code></pre>
<p><strong>Beispiel (main.cpp)</strong></p>
<pre><code class="language-cpp">#include &lt;iostream&gt; // std::cout
#include &lt;fstream&gt; // std::ifstream
#include &quot;measurements.hpp&quot; // measurements

int main()
{
    std::ifstream file_stream(&quot;C:\\Messadaten.dat&quot;);
    if (!file_stream) { std::cerr &lt;&lt; &quot;FEHLER: Datei nicht vorhanden!&quot; &lt;&lt; std::endl; return 1; }
    measurements data;
    file_stream &gt;&gt; data;
    std::cout &lt;&lt; data;

    std::cin.get();
}
</code></pre>
<p>Statt aus der Datei könnten nun auch einfach per (std::cin &gt;&gt; data) die Daten vom Benutzer eingegeben werden müssen, usw. usf.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1429657</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1429657</guid><dc:creator><![CDATA[*D*Evil]]></dc:creator><pubDate>Wed, 02 Jan 2008 23:54:16 GMT</pubDate></item><item><title><![CDATA[Reply to Programm mit Funktionen --&amp;gt; zu Klasse machen on Thu, 03 Jan 2008 00:58:44 GMT]]></title><description><![CDATA[<p>(D)Evil schrieb:</p>
<blockquote>
<p>Nun kann man hier das ein wenig kürzen, in dem man mit std::plus&lt;double&gt; und std::transform arbeitet, aber das wäre difinitiv über dem Niveau der restlichen Klasse <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>
</blockquote>
<p>du meinst wohl</p>
<pre><code class="language-cpp">return std::accumulate(data.begin(), data.end(), 0.0) / data.size();
</code></pre>
<p><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>die frage ist allerdings, ob der OP nicht so etwas wie min_element auch selbst implementieren soll.</p>
<p>PS. schon wieder std::endl?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1429673</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1429673</guid><dc:creator><![CDATA[queer_boy]]></dc:creator><pubDate>Thu, 03 Jan 2008 00:58:44 GMT</pubDate></item><item><title><![CDATA[Reply to Programm mit Funktionen --&amp;gt; zu Klasse machen on Thu, 03 Jan 2008 09:48:52 GMT]]></title><description><![CDATA[<p>Vielen Dank euch beiden für eure Antworten,</p>
<p>(D)Evil schrieb:</p>
<blockquote>
<p>Ach du Scheiße ..</p>
</blockquote>
<p>hehe <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="😉"
    /> das dachte ich auch als ich das Programm geschrieben habe, da ich eigentlich geglaubt habe, das Prinzip verstanden zu haben. Aber dies war wohl nicht 100% der Fall.:D</p>
<p>Hier ein paar Fragen zu deinem Lösungsvorschlag:</p>
<p>1. Du hast viele Library Funktionen benutzt die ich noch nie gehört habe wie z.b</p>
<p>size_t var()<br />
begin()<br />
end()<br />
push_back()</p>
<p>std::cerr<br />
std::size()</p>
<p>In welcher Bibliothek stehen diese drin? In der iostream?!<br />
size_t var()<br />
begin()<br />
end()<br />
push_back()</p>
<p>Die Funktion von push_back() ist mir noch etwas unklar.</p>
<pre><code class="language-cpp">friend std::istream&amp; operator&gt;&gt;(std::istream&amp; in, measurements&amp; data)
    {
        double tmp(0.0);
        while (in &gt;&gt; tmp) m_data.push_back(tmp);
        return in;        
    }
</code></pre>
<p>Es wird erstmal eine temp variable mit dem Rückgabewert double definiert,</p>
<pre><code class="language-cpp">double tmp(0.0);
</code></pre>
<p>danach wird der stream vom input File gestartet, alles bis zum nächsten Leerzeichen bzw. Leerzeile wird hierbei in tmp geschrieben.</p>
<pre><code class="language-cpp">in &gt;&gt; tmp
</code></pre>
<p>Mit der While schleife wird überprüft ob der stream true ist, in diesem Fall wird das was in tmp steht zu m_data übergeben.</p>
<p>Jetzt fehlt mir alledings die Kenntniss wie dieser Vector aussieht,<br />
In Mathe: Zeilenvector ( 0, 1, 0,....) Sieht dieser Vector auch so aus?<br />
Warum benutzt man dann hierzu kein gewöhnliches Array? Sondern benutzt diese Vector Funktion?</p>
<p>Wie kann ich die Ausgabedatei angeben? Weil momentan wird das ja nur auf Bildschirmconsole ausgegeben oder?<br />
so vllt.!?</p>
<pre><code class="language-cpp">ifstream input(&quot;C:\\MESS.DAT&quot;);
		if(!input)
			{
				cerr &lt;&lt; &quot;Die Datei konnte nicht geöffnet werden&quot;&lt;&lt; endl;
				//alternativ zu
				//cout &lt;&lt; &quot;Die Datei konnte nicht geöffnet werden&quot;&lt;&lt; endl;

				return 1;		
			}
		Messungen data;
		input &gt;&gt; data;
                ofstream output(&quot;C:\\ERGEBNIS.DAT&quot;);
		output &lt;&lt; data;

		cin.get();
</code></pre>
<p>mfg fraggelfragger</p>
<p>Ps: Soweit habe ich den Code nun: ( hier (Z32) error C2065: 'm_data': nichtdeklarierter Bezeichner)</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;

using namespace std;

class Messungen
	{
	private: //(bei Klasse ist dies Default-&gt; man kanns weglassen)

		vector&lt;double&gt; m_data;

	public:

		//Operatoren überladen
		friend istream&amp; operator&gt;&gt; (istream&amp; inFile, Messungen&amp; data);
		friend ostream&amp; operator&lt;&lt; (ostream&amp; outFile, Messungen const&amp; data);

		//Getter
		double mittelwert()const;
		double maximum()const;
		double minimum()const;

	};

istream&amp; operator&gt;&gt; (istream&amp; inFile, Messungen&amp; data)
	{
		double temp = 0.0;
		while (inFile &gt;&gt; temp)
			{
				m_data.push_back(temp);
			}

		return inFile;
	}
ostream&amp; operator&lt;&lt; (ostream&amp; outFile, Messungen const&amp; data)
	{
		return ( outFile &lt;&lt; &quot;Mittelwert: &quot; &lt;&lt; data.mittelwert() &lt;&lt; &quot;\nMaximum : &quot; &lt;&lt; data.maximum() &lt;&lt; &quot;\nMinimum : &quot; &lt;&lt; data.minimum());
	}

double Messungen::mittelwert()const
	{
		double temp=0.0;
		for(unsigned int i=0;i &lt; m_data.size(); i++)
			{
				temp *= m_data[i];
			}

		return temp/m_data.size();
	}

double Messungen::maximum()const
	{
		return *max_element(m_data.begin(),m_data.end());
	}
double Messungen::minimum()const
	{
		return *min_element(m_data.begin(), m_data.end());
	}

int main()
	{
		ifstream input(&quot;C:\\MESS.DAT&quot;);
		if(!input)
			{
				cerr &lt;&lt; &quot;Die Datei konnte nicht geöffnet werden&quot;&lt;&lt; endl;
				//alternativ zu
				//cout &lt;&lt; &quot;Die Datei konnte nicht geöffnet werden&quot;&lt;&lt; endl;

				return 1;		
			}
		Messungen data;
		input &gt;&gt; data;
		cout &lt;&lt; data;

		cin.get();
	}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1429748</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1429748</guid><dc:creator><![CDATA[fraggelfragger]]></dc:creator><pubDate>Thu, 03 Jan 2008 09:48:52 GMT</pubDate></item><item><title><![CDATA[Reply to Programm mit Funktionen --&amp;gt; zu Klasse machen on Thu, 03 Jan 2008 09:56:50 GMT]]></title><description><![CDATA[<blockquote>
<p>1. Du hast viele Library Funktionen benutzt die ich noch nie gehört habe wie z.b</p>
<p>size_t var()<br />
begin()<br />
end()<br />
push_back()</p>
<p>std::cerr<br />
std::size()</p>
<p>In welcher Bibliothek stehen diese drin? In der iostream?!<br />
size_t var()<br />
begin()<br />
end()<br />
push_back()</p>
</blockquote>
<p>. Die Container Klassen des Standards haben alle ein relativ ähnliches Interface, um die Arbeit damit leicht zu machen (.push_back(T) bsw. zum einfügen eines Elementes an das Ende des Containers, .size() zum Abfragen der Größe)</p>
<p>std::size_t ist laut Standard ein Datentyp zur Angabe von Größen und ist oftmals als unsigned int definiert.</p>
<p>begin() und end() geben jeweils sog. Interatorn zurück (des Containers). Iterator ist ein Design-Pattern (Entwurfsmuster) das dazu dient eine einheitliche Abhandlung der Datentypen zu gewähren. Sie dir z.B. einmal die Funktionen des &lt;algorithm&gt;-Header an. (Erklärung zu Iterator: <a href="http://de.wikibooks.org/wiki/Muster:_Iterator" rel="nofollow">http://de.wikibooks.org/wiki/Muster:_Iterator</a>)</p>
<p>std::size_t var(0) ist eine Variable vom Typ std::size_t die mit 0 initialisiert wird.</p>
<p>std::cerr ist ein Ausgabestream, ähnlich wie std::cout, doch für die Ausgabe von Fehlern vorgesehen. Wenn man sich streng daran hält, kann man nachher hingehen und diesen Stream z.B. in eine Datei umleiten und bekommt dann nur die Fehlermeldungen in die Datei <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>std::size() wo hast du das gefunden? Wenn dann als Memberfunktion einer Containerklasse.</p>
<blockquote>
<p>Die Funktion von push_back() ist mir noch etwas unklar.</p>
<pre><code class="language-cpp">friend std::istream&amp; operator&gt;&gt;(std::istream&amp; in, measurements&amp; data)
{
    double tmp(0.0);
    while (in &gt;&gt; tmp) m_data.push_back(tmp);
    return in;        
}
</code></pre>
</blockquote>
<p>Also, du musst push_back im Kontext sehen. push_back ist eine Memberfunktion der Klasse std::vector. std::vector ist ein dynamischer Array (vereinfacht gesagt!) d.h. die Daten liegen aufm Heap und die Größe muss nicht von vornerrein vorbestimmt sein, sondern du kannst sie während der Laufzeit verändern.</p>
<p>std::vector&lt;T&gt;::push_back(T const&amp; data) fügt am Ende des &quot;dynamsichen Array&quot; ein Item hinzu(data).</p>
<blockquote>
<p>Es wird erstmal eine temp variable mit dem Rückgabewert double definiert,</p>
<pre><code class="language-cpp">double tmp(0.0);
</code></pre>
<p>danach wird der stream vom input File gestartet, alles bis zum nächsten Leerzeichen bzw. Leerzeile wird hierbei in tmp geschrieben.</p>
<pre><code class="language-cpp">in &gt;&gt; tmp
</code></pre>
<p>Mit der While schleife wird überprüft ob der stream true ist, in diesem Fall wird das was in tmp steht zu m_data übergeben.</p>
</blockquote>
<p>Ehm ja, also als erstes lege ich in der tat eine Temporär Variable an, in die ich nun im folgenden einlesen.</p>
<p>in &gt;&gt; tmp ließt nun die Daten ein. Wenn das Ende der Datei erreich ist oder aus einem anderen Grund nichtmehr eingelesen werden kann, wird das failbit gesetzt (des Streams). operator&gt;&gt; von std::fstream gibt eine Referenz auf diesen wieder zurück. d.h. steht dann, wenn man das einlesen mal außer acht lässt, in der Schleife:</p>
<pre><code class="language-cpp">while (in)
</code></pre>
<p>. Dabei wird &quot;in&quot; per operator void* in einen void* Umgewandelt. Dieser nimmt NULL an (damit abbruch der Schleife!), wenn ein fail oder bad-bit gesetzt ist.</p>
<p>Wenn der Wert eingelesen wurde, wird er nun in den &quot;dynamsichen Array&quot; (m_data) gepackt (push_back).</p>
<blockquote>
<p>Jetzt fehlt mir alledings die Kenntniss wie dieser Vector aussieht, [...]<br />
kann ich mir das so vorstellen wie ein Array? warum benutzt man hierzu kein array?</p>
</blockquote>
<p>Im Prinzip schon. Es ist ein Array auf dem Heap. Um nun nicht bei jedem Hinzufügen eines Elements neu den Speicher anfordern zu müssen und alle Daten zu kopieren, geht std::vector hin und reserviert schonmal eine gewisse Menge an Speicher vor (so zu sagen <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="😉"
    /> ). Wenn auch der reservierte Bereich voll ist, wird ein noch größerer Bereich reserviert und die Daten aus dem alten Bereich werden in den neuen rüber kopiert.<br />
Das ist das Merkmal eines std::vector. Die Daten sind als ein Block gespeichert und nicht, wie bsw. eine std::list, die Daten quer über den Speicher verteilt.</p>
<p>Warum man hier keinen Array benutzt? Weil du dann auf die Größe angewiesen bist, die du vorher fest in deinem Programm angegeben hast (ok man kann sich da auch selber was schreiben(läuft aber auch übern Heap und nicht übern Stack) und das ist ja nicht unbedingt deine Absicht. Wie viele Daten nun in der Datei stehen weißt du ja nicht unbedingt vorher!</p>
<p>Hoffe das war erstmal genug zum Verständnis <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/1429759</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1429759</guid><dc:creator><![CDATA[*D*Evil]]></dc:creator><pubDate>Thu, 03 Jan 2008 09:56:50 GMT</pubDate></item><item><title><![CDATA[Reply to Programm mit Funktionen --&amp;gt; zu Klasse machen on Thu, 03 Jan 2008 10:54:26 GMT]]></title><description><![CDATA[<p>fraggelfragger schrieb:</p>
<blockquote>
<p>Vielen Dank euch beiden für eure Antworten,</p>
<p>(D)Evil schrieb:</p>
<blockquote>
<p>Ach du Scheiße ..</p>
</blockquote>
<p>hehe <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="😉"
    /> das dachte ich auch als ich das Programm geschrieben habe, da ich eigentlich geglaubt habe, das Prinzip verstanden zu haben. Aber dies war wohl nicht 100% der Fall.:D</p>
<p>Hier ein paar Fragen zu deinem Lösungsvorschlag:</p>
<p>1. Du hast viele Library Funktionen benutzt die ich noch nie gehört habe wie z.b</p>
<p>size_t var()<br />
begin()<br />
end()<br />
push_back()</p>
<p>std::cerr<br />
std::size()</p>
<p>In welcher Bibliothek stehen diese drin? In der iostream?!<br />
size_t var()<br />
begin()<br />
end()<br />
push_back()</p>
</blockquote>
<p>hm, da haben wir dich vielleicht etwas überfordert.<br />
std::cerr ist der standardfehlerausgabestream (tolles wörtchen), sowie std::cout der standardausgabestream ist. std::cerr schreibt in die fehlerausgabe, std::cout auf die standardausgabe (so kann man sich bei eigenen konsolenprogrammen dann beispielsweise die standardausgabe in eine datei umleiten und nur von der fehlerausgabe trennen). außerdem ist std::cerr ungepuffert, wohingegen std::cout gepuffert ist (deshalb mein hinweis auf das überflüssige endl. obwohl, endl ist eigentlich so gut wie immer überflüssig).</p>
<p>std::vector ist eine der container-klassen, die bei C++ quasi &quot;mit dabei&quot; sind. es repräsentiert ein dynamisches array, das sich automatisch um die speicherverwaltung kümmer, wenn bspw. neue elemente hinzugefügt werden. ist für dein beispiel etwas suboptimal, weil du ja genau weißt, wieviele messwerte eingelesen werden sollen.</p>
<p>begin, end, push_back, size sind elementfunktionen von vector, push_back fügt einfach ein element an das ende des vectors (des dynamischen arrays) ein, und kümmert sich automatisch um jegliche speicherverwaltung. begin und end liefern jeweils iteratoren auf das erste bzw. (nach)letzte element des vectors. iteratoren kannst du dir ein bisschen wie zeiger vorstellen, mit denen du durch ein array navigieren kannst. (sie sind bei vector auch meist als zeiger implementiert, muss aber nicht sein) die standardalgorithmen arbeiten nicht mit zeigern, sondern mit iteratoren, quasi eine abstrahierte form von zeigern. size letztendlich liefert dir einfach die anzahl der elemente in einem vector.<br />
size_t hat damit wenig zu tun, std::size_t ist einfach der standardtyp für größenangaben, definiert im header &lt;cstddef&gt;.</p>
<blockquote>
<pre><code class="language-cpp">istream&amp; operator&gt;&gt; (istream&amp; inFile, Messungen&amp; data)
    {
        double temp = 0.0;
        while (inFile &gt;&gt; temp)
            {
                m_data.push_back(temp);
            }

        return inFile;
    }
</code></pre>
</blockquote>
<p>m_data ist ein member der klasse data, d.h. um darauf zugreifen zu können brauchst du eine instanz. und wie man auf membervariablen zugreifen kann (und hier unterscheidet sich std::vector nicht von builtins wie int, double, ...), weißt du (wie ich weiß):</p>
<pre><code class="language-cpp">istream&amp; operator&gt;&gt; (istream&amp; inFile, Messungen&amp; data)
{
   double temp = 0.0;
   while (inFile &gt;&gt; temp)
   {
      data.m_data.push_back(temp); //m_data ist ein member von data und push_back ist eine memberfunktion von m_data.
   }
   return inFile;
}
</code></pre>
<blockquote>
<p>Jetzt fehlt mir alledings die Kenntniss wie dieser Vector aussieht,<br />
In Mathe: Zeilenvector ( 0, 1, 0,....) Sieht dieser Vector auch so aus?<br />
Warum benutzt man dann hierzu kein gewöhnliches Array? Sondern benutzt diese Vector Funktion?</p>
</blockquote>
<p>std::vector ist eine klasse <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="😉"
    /><br />
es vereinfacht das arbeiten mit rohem speicher. roher speicher ist schlecht, meistens nicht ausnahmesicher und es wirkt &quot;grob&quot;, damit zu hantieren. std::vector übernimmt z.b. jegliche speicherverwaltung, wenn er über seine grenzen hinaus wächst. generell sind solche containerklassen zu bevorzugen, zumal sie -relativ einheitlich- funktionen zum einfachen umgang mit ihnen bereitstellen. (bspw. iteratoren oder memberfunktionen wie size() usw.) du verwendest für strings ja auch std::string (ebenso eine containerklasse mit iteratoren und automatischer speicherverwaltung) und hantierst nicht selbst mit rohen char-zeigern herum <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>
<p>in deinem konkreten fall ist ein vector allerdings vielleicht doch nicht ganz angebracht. du hast zwei möglichkeiten, wenn du zur compile-zeit schon weißt, wie viele daten du einlesen willst: du verwendest die built-in arrays oder eine containerklasse für ebendiese.</p>
<p>erster fall: du nimmst statt dem vector ein array.</p>
<pre><code class="language-cpp">class Messungen
{
//...
private:
   double m_data[100];
//...
}
</code></pre>
<p>das stellt allerdings keine funktionen wie begin, end und size zur verfügung. size berechnest du in diesem fall mit</p>
<pre><code class="language-cpp">size_t size = sizeof(m_data)/sizeof(*m_data);
</code></pre>
<p>lies: size ist gleich die größe des arrays in bytes dividiert durch die größe des eines (in diesem fall des ersten) elements - ergibt die anzahl der elemente in dem array.</p>
<p>die eingabefunktion sieht dann so aus:</p>
<pre><code class="language-cpp">istream&amp; operator&gt;&gt; (istream&amp; inFile, Messungen&amp; data)
    {
        double temp = 0.0;
        int i = 0;
        while (inFile &gt;&gt; temp)
            {
                data.m_data[i++] = temp;
            }

        return inFile;
    }
</code></pre>
<p>die mittelwertfunktion musst du im hinblick auf die nicht mehr automatisch berechnete größe (&quot;size&quot;) ändern und die iteratoren für min_element und max_element sind dann zeiger auf das erste element des arrays und auf eins hinter dem letzten:</p>
<pre><code class="language-cpp">size_t size = sizeof(m_data) / sizeof(*m_data);
return min_element (m_data, m_data+size)
</code></pre>
<p>in der funktion mittelwert solltest übrigens nicht multiplizieren sondern addieren <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>die alternative sind gekapselte arrays. dafür gibt es std::tr1::array. den code musst du dabei dann nur bei der eingabe verändern, mittelwert und die anderen funktionen funktionieren dann so wie in (D)Evils beispiel. std::tr1::array liegt im header &lt;tr1/array&gt; und seine definition in Messungen sieht so aus:</p>
<pre><code class="language-cpp">class Messungen
{
//...
   std::tr1::array&lt;int, 100&gt; m_data;
//...
};
</code></pre>
<p>allerdings ist die wahrscheinlichkeit groß, dass entweder dein prof oder dein compiler std::tr1::array nicht kennen. beides ist nicht gut.</p>
<p>PS. ich sehe gerade mit der vorschaufunktion, dass (D)Evil bereits geantwortet hat.</p>
<blockquote>
<p>Warum man hier keinen Array benutzt? Weil du dann auf die Größe angewiesen bist, die du vorher fest in deinem Programm angegeben hast (ok man kann sich da auch selber was schreiben(läuft aber auch übern Heap und nicht übern Stack) und das ist ja nicht unbedingt deine Absicht. Wie viele Daten nun in der Datei stehen weißt du ja nicht unbedingt vorher!</p>
</blockquote>
<p>in diesem fall weiß er es <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="🙂"
    /> natürlich ist deine version einfacher erweiterbar.</p>
<p>PPS.<br />
ich habe lang überlegt, ob ich dir (fraggelfragger) vielleicht noch kurz etwas über klassen und objekte erzählen soll. ich habe zeit <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>
<p>in C++ hast du zwei arten von funktionen, sogenannte &quot;freie&quot; funktionen, das sind funktionen in der art</p>
<pre><code class="language-cpp">int foo ();

int bar ()
{
}

int main ()
{
}
</code></pre>
<p>und memberfunktionen, die als member einer klasse definiert sind. so z.b.</p>
<pre><code class="language-cpp">class Foo
{
public: 
   void bar ();
   void foo ();
   void bar (int, int);
};
</code></pre>
<p>eine klasse ist eine vorlage, eine vorlage für eine spezifische art von objekten. ein objekt ist ein konkretes ding, das im speicher liegt. eine klasse, die ja nur eine vorlage ist, gibt es im speicher deines programmes letztendlich gar nicht. du arbeitest immer nur mit objekten, d.i. mit instanzen einer klasse. du kannst von einer klasse (außer du verbietest es explizit) mehrere instanzen anlegen:</p>
<pre><code class="language-cpp">class Bar
{
public:
   int i;
};

//...
Bar a;
Bar b;
Bar c;
</code></pre>
<p>zeile 1-5 beschreiben, wie ein objekt vom typ Bar (<strong>klass</strong>issfiziert als Bar, klasse wird hier ein bisschen so verwendet wie in der biologie) auszusehen hat: es hat einen einzigen, öffentlichen member, und das ist ein int mit dem namen i. jede der drei instanzen (a, b und c) sieht nun genauso aus: jede hat einen integer namens i, auf den man zugreifen kann:</p>
<pre><code class="language-cpp">a.i = 42;
b.i = 23;
c.i = 5;
</code></pre>
<p>analog kannst du memberfunktionen definieren, die du für jede instanz der klasse separat aufrufen kannst. in unserem beispiel:</p>
<pre><code class="language-cpp">class Bar
{
public:
   int i;
   void foo ();
};

void Bar::foo ()
{
   cout &lt;&lt; &quot;in Bar::foo\n&quot;;
}

//...
Bar a, b, c;
a.foo();
b.foo();
c.foo();
</code></pre>
<p>foo wird in diesem fall für jede instanz aufgerufen. das besondere an memberfunktionen ist, dass sie in jedem fall, auch in unserem - und auch wenn es nicht so aussieht - ein argument mitübergeben bekommen, dieses ist der this-pointer. dieser zeiger zeigt auf gerade jene instanz, für die die memberfunktion aufgerufen wurde. rufst du <code>a.foo()</code> auf, zeigt this auf die adresse von a, bei b und c analog.</p>
<p>memberfunktionen funktionieren also wie freie funktionen, deren erster parameter ein zeiger auf eine struktur ist. in C könntest du das ungefähr so nachbilden:</p>
<pre><code class="language-cpp">struct Bar
{
   int i;
};

void foo (Bar* this)
{
    cout &lt;&lt; &quot;in Bar::foo\n&quot;;
}

//...
Bar a, b, c;
foo (&amp;a);
foo (&amp;b);
foo (&amp;c);
</code></pre>
<p>das verstehen des mechanismus &quot;dahinter&quot; hilft dir vielleicht, besser mit klassen und instanzen zurecht zu kommen.</p>
<p>zurück zu den memberelementen (oder auch: elementvariablen)<br />
da jede instanz ihre eigenen elementvariablen hat und der this-zeiger ein zeiger auf die instanz ist, für die die aktuelle memberfunktion aufgerufen wurde, kannst du über den this-zeiger auf die membervariablen der einen instanz (für die die funktion aufgerufen wurde) zugreifen:</p>
<pre><code class="language-cpp">class Bar
{
public:
   int i;
   void foo ();
};

void Bar::foo ()
{
   cout &lt;&lt; &quot;in Bar::foo. member i = &quot; &lt;&lt; this-&gt;i &lt;&lt; '\n';
}

//...
Bar a, b, c;
a.i = 42;
b.i = 23;
c.i = 5;

a.foo(); //gibt 42 aus
b.foo(); //gibt 23 aus
c.foo(); //gibt 5 aus
</code></pre>
<p>mit dem nötigen hintergrundwissen über den this-zeiger solltest du also nun verstehen, warum jeweils unterschiedliche zahlen ausgegeben werden - es wird schließlich foo() jeweils für unterschiedliche instanzen (derselben klasse) aufgerufen.</p>
<p>nun wäre es umständlich, in allen memberfunktionen &quot;this-&gt;&quot; zu schreiben, deshalb ist es erlaubt, diesebn expliziten zugriff wegzulassen.<br />
Bar::foo könnten wir deshalb auch so implementieren:</p>
<pre><code class="language-cpp">void Bar::foo ()
{
    cout &lt;&lt; i;
    //gleichbedeutend mit: cout &lt;&lt; this-&gt;i;
}
</code></pre>
<p>dass das nur in memberfunktionen funktioniert, sollte dir nun auch klar sein, denn eine freie funktion hat den zusätzlichen parameter &quot;this&quot; nun einmal nicht.</p>
<p>weiter: eine funktion, die als friend deklariert wird, ist <strong>keine</strong> memberfunktion der klasse. (alle memberfunktionen der klasse sind automatisch ihr &quot;friend&quot;, alles andere wäre auch unsinnig). deshalb hat sie auch keinen this-zeiger und deshalb musst du oben in deinem operator &lt;&lt; auch eine referenz auf ein Messungen-objekt übergeben.</p>
<p>ich hoffe, das macht dir einiges klarer und verständlicher. wenn du noch fragen hast, stell sie <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/1429801</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1429801</guid><dc:creator><![CDATA[queer_boy]]></dc:creator><pubDate>Thu, 03 Jan 2008 10:54:26 GMT</pubDate></item></channel></rss>