Eigenen Datentyp?



  • Hacker schrieb:

    1. Kein return 0;
    2. Kein system("pause");
    3. Du hast den Destruktor nicht definiert -> lösch die " ~meinDatentyp(); " Zeile wenn er sowieso trivial sein soll
    4. Den Konstruktor hast du ebenso wenig definiert -> änder in Zeile 24

    void meinDatentyp::init(int n)
    

    zu

    void meinDatentyp::meinDatentyp(int n)
    

    Soviel erstmal.
    Bitte Initialisierungs-listen verwenden:

    void meinDatentyp::meinDatentyp(int n):
    feld( new int[n]() )
    {
    }
    

    Mit dem () nach den Indiz-Klammern wird automatisch alles mit 0 initialisiert.

    void meinDatentyp::min()
    {
        int ergebnis = 0;
        float mittelwert = 0;//wird nicht verwendet (sollte warnungen geben)
        for(int i(0); i < n; i++)
            ergebnis = ergebnis + feld[i];
    
        std::cout << "Mittelwert = " << static_cast<float>(ergebnis) / n; // C++-Casts
    }
    

    NIE using namespace ...; in Headern!

    srand(...) muss in die main() (wird nur einmal ausgeführt)

    Danke, hab das jetzt mal alles umgesetzt und es scheint zu funktionieren! Danke!

    Ich hätt hier übrigens wieder ein neues "Problem". Die methode "add" soll mir das Ergebnis der Matrizenaddition zurückgeben. Wenn ich allerdings "return ergebnis;" am Ende der methode schreibe, mosert der Compiler, dass "ergebnis" deklariert sei! Was hat das zu bedeuten? Hier der Code:

    #include<iostream>
    using namespace std;
    
    class matrix
    {
    private:
    	int m;
    	int n;
    	int size;
    	int *feld;
    
    public:
    	matrix(int m, int n);
    	~matrix();
    
    	void init();
    	void print();
    	void input();
    	matrix *add(matrix *M);
    	void mult();
    };
    
    matrix::matrix(int m, int n)
    {
    	this->m = m;
    	this->n = n;
    
    	size = m*n;
    
    	feld = new int [size];
    }		//Konstruktor
    
    matrix::~matrix()
    {
    	delete feld;
    }		//Destruktor
    
    void matrix::init()
    {
    	for(int i=0; i<size; i++)
    	{
    		feld[i] = 0;
    	}
    }
    
    void matrix::print()
    {
    	int counter = 0;
    
    	for(int i=0; i<m; i++)
    	{
    		for(int j=0; j<n; j++)
    		{
    			cout << feld[counter++];
    		}
    		cout << endl;
    	}
    }
    
    void matrix::input()
    {
    	for(int i=0; i<size; i++)
    	{
    		cout << "Wert " << i << " eingeben: ";
    		cin >> feld[i];
    	}
    }
    
    matrix *matrix::add(matrix *M)
    {
    	if((M->m != m) || (M->n != n))
    	{
    		cout << "Matrizen nicht gleich gross! Abbruch!";
    	}
    	else
    	{
    		matrix *ergebnis = new matrix (m,n);
    
    		for(int i=0; i<size; i++)
    		{
    			ergebnis->feld[i] = feld[i] + M->feld[i];
    		}
    	}
    
    return ergebnis;
    }
    
    int main()
    {
    	matrix myMatrix(2,2), myMatrix_M(2,2);
    
    	myMatrix.init();
    	myMatrix.input();
    	myMatrix.print();
    
    	myMatrix_M.init();
    	myMatrix_M.input();
    	myMatrix_M.print();
    
    	myMatrix.add(&myMatrix_M);
    
    }
    

    PS: Das "using namespace std;" hab ich jetzt dennoch mal drin gelassen, da es mir jetzt zu aufwändig war, überall den Scope-Operator zu setzen! Sorry, aber das is mir echt zu viel Aufwand, auch wenn es "poor-style" is!



  • vip@r schrieb:

    Ich hätt hier übrigens wieder ein neues "Problem". Die methode "add" soll mir das Ergebnis der Matrizenaddition zurückgeben. Wenn ich allerdings "return ergebnis;" am Ende der methode schreibe, mosert der Compiler, dass "ergebnis"

    nicht deklariert sei! Dann pack return ergebnis vor die vorletzte } .

    Und eine weitere gute Frage wäre: Who deletes that object?



  • matrix *matrix::add(matrix *M)
    {
        if((M->m != m) || (M->n != n))
        {
            cout << "Matrizen nicht gleich gross! Abbruch!";
        }
        else
        {
            matrix *ergebnis = new matrix (m,n);
    
            for(int i=0; i<size; i++)
            {
                ergebnis->feld[i] = feld[i] + M->feld[i];
            }
        }
    
    return ergebnis;
    }
    

    Er meckert, dass es nicht deklariert ist. Ist es auch nicht. Wie dir (schon lange hoffe ich) klar sein dürfte, bilden Bereiche in den geschweiften Klammern eigene Namensräume (danke an gugelmoser) scopes aus. Es müsste wahrscheinlich so aussehen:

    matrix *matrix::add(matrix *M)
    {    
        if(M->m != m || M->n != n)
        {
            std::cout << "Matrizen nicht gleich gross! Abbruch!";//Hier kannst du ja auch was werfen
            return 0;
        }
    
        matrix *ergebnis = new matrix (m,n);
    
        else
            for(int i=0; i < size; i++)
                ergebnis->feld[i] = feld[i] + M->feld[i];
    
          return ergebnis;
    }
    


  • Hacker schrieb:

    bilden Bereiche in den geschweiften Klammern eigene Namensräume aus.

    Namensraum ist hierfür das falsche Wort.



  • Gugelmoser schrieb:

    Hacker schrieb:

    bilden Bereiche in den geschweiften Klammern eigene Namensräume aus.

    Namensraum ist hierfür das falsche Wort.

    Korrigiert.



  • Hacker schrieb:

    Gugelmoser schrieb:

    Hacker schrieb:

    bilden Bereiche in den geschweiften Klammern eigene Namensräume aus.

    Namensraum ist hierfür das falsche Wort.

    Korrigiert.

    :p Das nennt sich compound statement (Verbundanweisung / Block). Und eine Verbundanweisung führt einen local scope / block scope ein.



  • What the? Matrixaddition gibt Speicher zurück den man wieder freigeben muss? Ist das ernst gemeint? 😉



  • cooky451 schrieb:

    Ist das ernst gemeint? 😉

    Vermutlich nicht so ganz, sondern einfach nur von einer der zig bestehenden Uralt-Bibliotheken inspiriert, die genau solche Dummheiten machen. Sowas von 90er 😉



  • Danke für eure Antworten! Dass diese Variable im compound statment der else-Abzweigung gültig ist, ist mir natürlich schon länber bewusst. Ich hab halt nur noch nicht so die große Erfahrung, dass ich solche Fehler auf Anhieb sehe. Danke an euch!

    Gugelmoser schrieb:

    Und eine weitere gute Frage wäre: Who deletes that object?

    Dass hier noch nicht zerstört wird, ist auch klar. Das sollte ich wohl auch noch implementieren. Danke! Ich liefere bei Gelegenheit den gesamten Code nach. Wahrscheinlich heute noch.

    pumuckl schrieb:

    cooky451 schrieb:

    Ist das ernst gemeint? 😉

    Vermutlich nicht so ganz, sondern einfach nur von einer der zig bestehenden Uralt-Bibliotheken inspiriert, die genau solche Dummheiten machen. Sowas von 90er 😉

    Bitte zerreisst halt meinen Code jetzt nicht in so große fetzen. Es funktioniert. Ich bin halt noch etwas unerfahren. Übung macht den Meister und nur durch die Fehler bei der Übung lernt man. Wie hättet ihr denn das gemacht? Mir war halt einfach nur diese Möglichkeit in den Sinn gekommen, dass die Additionsfunktion einen Speicherbereich auf das Ergebnis zurückgibt!


  • Mod

    vip@r schrieb:

    Bitte zerreisst halt meinen Code jetzt nicht in so große fetzen. Es funktioniert.

    Das ist kein gutes Kriterium. Eine Bruchbude, die beim ersten Windstoß einfällt, nennst du auch nicht Haus, bloß weil es momentan noch hält.

    Ich bin halt noch etwas unerfahren. Übung macht den Meister und nur durch die Fehler bei der Übung lernt man. Wie hättet ihr denn das gemacht?

    Guck doch auf der ersten Seite! Da habe ich einen langen Roman mit vielen googlebaren Stichwörtern geschrieben, wie man den Code ganz einfach (sogar einfacher als er momentan ist!) viel robuster machen kann, so dass man sich um gar nichts mehr sorgen braucht und es einfach funktioniert. Außerdem habe ich dir erklärt, was am Momentanen Code nicht so gut ist.

    Dein Beitrag auf Seite 3 hat mich dann doch etwas entsetzt 😡 , denn wie es scheint, hast du dir nicht einmal die Mühe gemacht, meine Erklärungen auch nur quer zu lesen, geschweige denn, dich mal mit den Stichworten weiterzubilden.



  • SeppJ schrieb:

    Dein Beitrag auf Seite 3 hat mich dann doch etwas entsetzt 😡 , denn wie es scheint, hast du dir nicht einmal die Mühe gemacht, meine Erklärungen auch nur quer zu lesen, geschweige denn, dich mal mit den Stichworten weiterzubilden.

    Bevor du hier mich mit irgendwelche bösen Smileys in die Schranken versuchst zu weisen, solltest du vielleicht vorher überhaupt erstmal wissen, dass ich laut meiner Aufgabe eine Methode init() schreiben soll, die das mit "new int [size]" allokierte Array mit 0en initialisiert! Wenn ich nun mit "new int [size] ()" im Konstruktor das allokierte Array schon mit 0en belege, wird die Methode "init()" überflüssig. Ich MUSS aber eine Methode init() schreiben" Somit kann ich auf deinen Verbesserungsvorschlag nicht eingehen, weil ich sonst mein Übungsziel nicht erreiche, welches ja ist, eine Methode "init() zu schreiben"!

    SeppJ schrieb:

    Ich nehme mal an, du machst das nur zur Übung und nicht, weil du std::vector nicht kennst:

    Doch, "vector" kenn ich. Darf/soll ich nur nicht benutzen!

    Nichtsdestotrotz halte ich mal noch weiterhin an meinem "schlechtn Code" fest. Denn ehrlich gesagt hilft mir nur mein Code weiter;

    .
    .
    .
    matrix *matrix::add(matrix *M)
    {
    	if((M->m != m) || (M->n != n))
    	{
    		cout << "Matrizen nicht gleich gross! Abbruch!";
    	}
    	else
    	{
    		matrix *ergebnis = new matrix (m,n);
    
    		for(int i=0; i<size; i++)
    		{
    			ergebnis->feld[i] = feld[i] + M->feld[i];
    		}
    
    	return ergebnis;
    	}
    }
    
    int main()
    {
    	matrix myMatrix(2,2), myMatrix_M(2,2);
    
    	myMatrix.init();
    	myMatrix.input();
    	myMatrix.print();
    
    	myMatrix_M.init();
    	myMatrix_M.input();
    	myMatrix_M.print();
    
    	myMatrix.add(&myMatrix_M);
    
    system("pause");
    return 0;
    }
    

    Das return ergebnis liefert nun einen Speicherbereich zurück. Wie kann ich mir nun in der main-Fkt. mir das Ergebnis lassen? Das versteh ich grad nicht. Wenn ich bspw. "cout << myMatrix.add(&myMatrix_M);" schreibe, dann wird nur die Adresse ausgegeben an der das Ergebnis steht, nicht aber die berechneten Werte selbst...


  • Mod

    vip@r schrieb:

    Bevor du hier mich mit irgendwelche bösen Smileys in die Schranken versuchst zu weisen, solltest du vielleicht vorher überhaupt erstmal wissen, dass ich laut meiner Aufgabe eine Methode init() schreiben soll, die das mit "new int [size]" allokierte Array mit 0en initialisiert!

    Dann reich das an deinen Lehrer weiter. Ich hoffe, du wirst hoffentlich aus dem Kurs nur eine gute Note mitnehmen und den Inhalt anschließend vergessen.

    Das return ergebnis liefert nun einen Speicherbereich zurück. Wie kann ich mir nun in der main-Fkt. mir das Ergebnis lassen? Das versteh ich grad nicht. Wenn ich bspw. "cout << myMatrix.add(&myMatrix_M);" schreibe, dann wird nur die Adresse ausgegeben an der das Ergebnis steht, nicht aber die berechneten Werte selbst...

    Da ich gerade 5 Seiten Thread nicht vollstandig lesen mag: Ist der Wahnsinn, ein mit new angefordertes Objekt per Pointer aus der Additionsmethode herauszugeben (anstatt wie üblich ein "richtiges" Objekt) auch eine Vorgabe oder deine eigene Idee? Falls letzteres: Eine Addition im Sinne von a + b sollte ein neues (const) Objekt als Rückgabewert haben (dieser Fall liegt hier vor), eine Addition im Sinne von a += b sollte eine Referenz auf *this als Rückgabewert haben (nur zur Info). Dies anders zu machen führt erfahrungsgemäß nur zu Scherereien, insbesondere das Übertragen von Objektverantwortung (wie hier durch das herausgeben eines noch freizugebenden Speicherbereichs) ist eine Todsünde.

    Wenn ich bspw. "cout << myMatrix.add(&myMatrix_M);" schreibe, dann wird nur die Adresse ausgegeben an der das Ergebnis steht, nicht aber die berechneten Werte selbst...

    myMatrix.add(&myMatrix_M) ist ja auch ein Zeiger auf das Ergebnis, nicht das Ergebnis selber. Du müsstest den Zeiger schon noch dereferenzieren, um an das Ergebnis zu kommen. Aber wie oben erklärt, ist das sowieso eine ungünstige* Methode, das überhaupt mit Pointern zu machen.

    *: Um deine empfindlichen Gefühle zu schonen nenne ich das nur "ungünstig" anstatt "totalen Bockmist", der es eigentlich ist. Wirst du die Stelle nun trotzdem ändern oder wiegst du dich durch die Vermeidung von Klartext meinerseits nun in Sicherheit, da "ungünstig" ja nicht so schlimm ist?



  • SeppJ, SeppJ! Guck mal, was ich gebastelt hab! Ich mache es später noch mit einem Allokator.



  • Und.. was soll das bringen?



  • So Leute!

    @SeppJ: Ich werd mir deine Ausführungen zu Gemüte führen, aber in einer ruhigen Minute. Dafür hab ich jetzt keine Zeit. Deine Sachen mögen ja wirklich 100%ig-Intelligent sein, aber einem Anfänger wie mich überfordert das leider auch zu 100%. Da solltest du vielleicht desöfteren drauf achten. Im übrigen kannst du meinen Code ruhig Bockmist nennen. Ich kann's nun mal (noch) nicht besser. Auf jeden Fall dennoch mal dankeschön für deine Hilfe!

    So hier dann noch kurz zum nächsten Problem: Ich muss jetzt noch eine Matrixmultiplikation machen. Ich hab hier schon mal angefangen aber ich drehe mich im Kreis und komme damit nicht zu recht. Ich hoffe ihr könnt mir auf die Sprünge helfen!

    matrix *matrix::mul(matrix *M)
    {
    	if((M->m) == n)	//m = Zeile, n = Spalte
    	{
    		int temp1 = 0, temp2 = 0;
    		matrix *ergebnis = new matrix (m, M->n);
    		int ergebnis_size = m * (M->n);
    
    		for(int i=0; i<ergebnis_size; i++)
    		{
    			for(int j=0; j<(M->n); j=j+(M->n))
    			{
    				temp1 = M->feld[j];
    
    				for(int k=0; k<n; k++)
    				{
    					temp2 = feld[k];
    					ergebnis->feld[i] = 
    
    				}
    
    			ergebnis->feld[i] = 
    			}
    
    			ergebnis->feld[i] = temp;
    		}
    	}
    	else
    	{
    		cout << "Matrizen stimmen nicht ueberein! Abbruch!";
    		return 0;
    	}
    }
    

    Diese Methode kommt aus der Klasse die ich oben schon gepostet hab. Ich brauch halt nun nur einen Ablauf, der mir zwei Matrizen miteiner multipliziert. Vielleicht kann mir ja jemand Stück für Stück helfen!

    Danke!



  • cooky451 schrieb:

    Und.. was soll das bringen?

    Ich find's lustig. 😉
    Ich meine, du musst die Objekte nicht wieder freigeben (bzw. den Speicher).
    Außerdem wird der Speicher erst beim Ende des Programms gelöscht, was zwischenzeitliche Performance-einbußen wegmacht (und, wie ich leider gerade feststellte, riesige Speicherlecks erzeugt, wenn das "Ende" nie erreicht wird - was allerdings wiederum mit der programmier-kunst des Programmierers zusammenhängt).


  • Administrator

    Hacker schrieb:

    SeppJ, SeppJ! Guck mal, was ich gebastelt hab! Ich mache es später noch mit einem Allokator.

    Du weisst schon, dass dein Code verschiedene Fehler hat und zudem undefiniertes Verhalten auslöst? Zudem hat er auch noch einige Unschönheiten drin.

    Grüssli

    PS: Falls du mehr erfahren willst, solltest du einen eigenen Thread starten.



  • Dravere schrieb:

    ...
    PS: Falls du mehr erfahren willst, solltest du einen eigenen Thread starten.

    War doch nur aus spaß! 😃



  • Hacker schrieb:

    Außerdem wird der Speicher erst beim Ende des Programms gelöscht, was zwischenzeitliche Performance-einbußen wegmacht

    Na super, das kannste auch alle major Betriebssysteme für dich machen lassen, die machen das sogar wesentlich effizienter als dein Zeugs. 😉

    @vip@r
    http://www.c-plusplus.net/forum/301055-2



  • Hacker schrieb:

    SeppJ, SeppJ! Guck mal, was ich gebastelt hab! Ich mache es später noch mit einem Allokator.

    Das ist nicht nur hässlich sondern auch noch falsch. Dein Move-Ctor ist ein kaputter Copy-Ctor. Da du nicht auf Alignment geachtet hast, handelst du dir herrlich UB ein. Ansonsten gehe ich darauf nicht mehr ein, cookies Kommentar triffts am besten.


Anmelden zum Antworten