Frage/Problem: Klasse A erstellt Instanz aus Klasse B



  • Hallo C++ Community!

    Ich beschäftige mich derzeit mit dem Konzept von OOP, sowie Syntax und Semantik.
    Nun bin ich auf folgendes Problem gestoßen:

    Es wurden zwei Klassen erstellt: Menu und Vektoren.
    In der Main-Funktion wird lediglich eine Instanz oMenu erstellt, welche auch direkt folgendermaßen geöffnet wird:
    oMenu.fMenu();

    Nun besteht die Auswahl verschiedene Rechenoperationen durchzuführen.
    Für die Berechnung des Skalarproduktes sind zwei Vektoren erforderlich.
    Nun wird die Dimension abgefragt und die Werte, welche in einem Array gespeicher werden (abhängig von der Dimension).
    Nun erstellen wir also zwei Instanzen VektorA und VektorB aus der Klasse Vektoren und übergeben die Werte Dimension und die Arrays (entweder als Konstruktor oder als Funktion fSetWerte).
    Die Werte können mittels einer Funktion fGetWerte abgerufen werden.

    Und hier ist das Problem:
    Wenn VektorA seine Werte übergeben bekommt sind diese zunächst abrufbar. Allerdings ist dies nicht mehr möglich, wenn der zweite VektorB seine Werte übergeben bekommt. Dann sind nur noch die Werte von VektorB abrufbar. Die von VektorA werden gelöscht.
    Wo ist hier das Problem?

    Ich benutze Dev C++ und den Compiler TDM-GCC 4.6.1 64-bit (Windows 8).

    Hoffentlich kennt sich einer mit diesem Problem aus und kann mir sagen,
    was genau hier schief läuft.

    Vielen Dank im Voraus!! 🙂

    Hier ist der/die Code/s:
    Anmerkung: Zu Testzwecken wurde noch ein dritter VektorC erstellt, um das Problem zu ermitteln.

    Main-Funktion:

    #include <iostream> 
    #include <iomanip>
     #include <cstdlib> 
     #include <cstdio>
     #include <string>
     #include <bitset>
     #include <math.h>
     #include <cmath>
     #include <conio.h>
    
    #include "vektoren.h"
    #include "menu.h"
    
    using namespace std;
    
    int main(int argc, char *argv[]) {
    	Menu oMenu;
    	while(true){oMenu.fMenu();}
    	return 0;
    }
    

    Menu-Header

    #ifndef MENU_H
    #define MENU_H
    
    using namespace std;
    
    class Menu
    {
    	private:
    		char cAuswahl;
    		int iDim;
    		double dVec1[3], dVec2[3], dVec3[3];
    
    	public:
    		//Konstruktor//
    		Menu();
    		//Destruktor//
    		~Menu();
    
    		//Menüaufruf
    		void fMenu(void);
    
    		//Rechenaufruf
    		void fVektorlaenge();
    		void fSkalarprodukt();
    
    		//Set-Funktionen
    		char setAuswahl();
    };
    
    #endif // MENU_H
    

    Menu.cpp

    #include <iostream> 
    #include <iomanip>
     #include <cstdlib> 
     #include <cstdio>
     #include <string>
     #include <bitset>
     #include <math.h>
     #include <cmath>
     #include <conio.h>
    
    #include "vektoren.h" 
    #include "menu.h" // class's header file
    
    using namespace std;
    
    //Konstruktor//
    Menu::Menu(){}
    //Destruktor//
    Menu::~Menu(){cout << "Menu zerstoert";}
    
    void Menu::fMenu(){
    
    	while(true){
    		system("cls");
    		cout << endl << endl
    			 << "Rechner Vektoren" << endl
    			 << "Funktionen:" << endl 
    			 << "1: Vektorlaenge"<<endl
    			 << "2: Skalarprodukt " << endl
    			 << "3: Einheitsvektor " << endl
    			 << "4: Winkel zwischen zwei Vektoren " << endl
    			 << "5: Vektor-Addition" << endl
    			 << "6: Vektor-Subtraktion" << endl
    			 << "e: Exit" <<endl<<endl;
    
    		this->cAuswahl = getch();
    
    		switch(this->cAuswahl){
    				case '1':
    					return fVektorlaenge();
    					break;
    
    			    case '2':
    					fSkalarprodukt();
    					break;
    				/*
    			case '3':
    				{
    				double vector[3];
    				cout<< "Geben Sie die Koordinaten x y z des Vektors 1 ein: " << endl;
    				cin >> vector[0];
    				cin >> vector[1];
    				cin >> vector[2];
    				cout << endl << fVecEinheit(vector) << endl;
    				}
    				break;
    
    			case '4':
    				{
    				double vec2[3], vec1[3];
    				cout<< "Geben Sie die Koordinaten x y z des Vektors 1 ein: " << endl;
    				cin >> vec1[0];
    				cin >> vec1[1];
    				cin >> vec1[2];
    
    				cout<< "Geben Sie die Koordinaten x y z des Vektors 2 ein: " << endl;
    				cin >> vec2[0];
    				cin >> vec2[1];
    				cin >> vec2[2];
    
    				cout<<endl << fVecWinkel(vec1,vec2) << endl;
    				}
    				break;
    			*/
    			case 'e':
    				exit(0);
    			default:
    				cout<< "Fail";
    				break;
    		}
    
    	}
    
    	return;
    }
    
    void Menu::fVektorlaenge(){
    		cout << "Anzahl Dimensionen: ";
    		cin >> this->iDim;
    		double dVec[iDim];
    		cout<< endl << "Geben Sie Werte ihres Vektors ein: " << endl;
    		for(int i = 0;i<this->iDim;i++){
    				cout << endl << i+1 << ". Wert: ";
    				cin >> dVec[i];
    				}
    		Vektoren Vektor( dVec , &this->iDim );
    		cout << endl << "Der Vektor hat die Laenge: " << Vektor.fVecLength() << endl;
    		cout << "Druecke eine Taste um fortzufahren" << endl;
    		getch();
    		}
    
    void Menu::fSkalarprodukt(){
    
    					Vektoren VektorA;
    					Vektoren VektorB;
    					Vektoren VektorC;
    
    					cout << "Anzahl Dimensionen: ";
    					cin >> this->iDim;
    
    					cout << endl << "Dim: " <<  this->iDim << endl;
    
    					cout<< endl << "Geben Sie Werte ihres ersten Vektors ein: " << endl;
    					for(int i = 0; i < this->iDim ;i++){
    						cout << endl << i+1 << ". Wert: ";
    						cin >> dVec1[i];
    						}
    
    					cout<< endl << "Geben Sie Werte ihres zweiten Vektors ein: " << endl;
    					for(int j = 0; j < this->iDim ;j++){
    						cout << endl << j+1 << ". Wert: ";
    						cin >> dVec2[j];
    						}
    
    					cout<< endl << "Geben Sie Werte ihres dritten Vektors ein: " << endl;
    					for(int k = 0; k < this->iDim ;k++){
    						cout << endl << k+1 << ". Wert: ";
    						cin >> dVec3[k];
    						}
    
    					VektorA.fSetWerte(dVec1,&iDim);
    					VektorB.fSetWerte(dVec2,&iDim);
    					VektorC.fSetWerte(dVec3,&iDim);
    
    					VektorA.fGetWerte();
    					VektorB.fGetWerte();
    					VektorC.fGetWerte();
    
    					VektorA.fVecSkalar( dVec2 );
    					cout << "Druecke eine Taste um fortzufahren" << endl;
    					getch();
    }
    

    Vektoren-Header

    #ifndef VEKTOREN_H
    #define VEKTOREN_H
    
    class Vektoren
    {
    	private:
    		unsigned int iXyz; //Anzahl Dimensionen des Vektors
    
    		double dVec[]; //Vektor
    
    	public:
    				//Konstruktor
    		//Vektoren(double dVec[],int iXyz);
    		Vektoren();
    		Vektoren(double *dVec,int *iXyz);
    				//Destruktor
    		~Vektoren();
    
    				//Set-Funktion
    		void fSetWerte(double *dVec,int *iXyz);		
    				//Get-Funktionen
    		void fGetWerte();
    		double fGetVektor();
    
    				//Rechenfunktionen
    		double fVecLength();
    		double fVecSkalar(double *dVecOther);
    		double fVecEinheit(double* vector);
    		double fVecWinkel(double* vec1, double* vec2);
    
    };
    
    #endif // VEKTOREN_H
    

    Vektoren.cpp

    #include <iostream> 
    #include <iomanip>
     #include <cstdlib> 
     #include <cstdio>
     #include <string>
     #include <bitset>
     #include <math.h>
     #include <cmath>
     #include <conio.h>
    
    #include "vektoren.h" 
    
    using namespace std;
    
    // class constructor
    Vektoren::Vektoren(double *dVec,int *iXyz)
    {
    	this->iXyz = *iXyz;
    	for(int i = 0; i < this->iXyz;i++){
    	this->dVec[i] = dVec[i];
    	}
    }
    
    Vektoren::Vektoren(){ }
    // class destructor
    Vektoren::~Vektoren()
    {
    	cout << endl << "ACHTUNG! Vektor-Objekt zerstört!" << endl;
    }
    
    //Get-Funktionen
    void Vektoren::fGetWerte(){
    	cout << endl << "Dimensionen: " << this->iXyz;
    	for(int i = 0; i < this->iXyz;i++){
    		cout << endl << i+1 << ". Komponente: " << this->dVec[i];
    	}
    	cout << endl;
    }
    
    double Vektoren::fGetVektor(){
    	for(int i = 0; i < this->iXyz;i++){
    		dVec[i] = this->dVec[i];	
    	}
    	return dVec[iXyz];
    }
    
    //Set-Funktionen
    void Vektoren::fSetWerte(double *dVec, int *iXyz){
    	this->iXyz = *iXyz;
    	for(int i = 0; i < this->iXyz;i++){
    		this->dVec[i] = dVec[i];
    		}
    	}
    
    		//Skalarprodukt
    double Vektoren::fVecSkalar( double *dVecOther ){
    	double dVec2;
    	for(int i = 0; i < this->iXyz;i++){
    		cout << "This: " << dVec[i] << endl << "Other: " << dVecOther[i] << endl;
    		dVec2 += this->dVec[i] * dVecOther[i];
    	}
    
    	return dVec2; 
    }
    
    		//Länge des Vektors
    double Vektoren::fVecLength( ){
    	double dVec2;
    	for(int i = 0; i < this->iXyz;i++){
    		dVec2 += pow( this->dVec[i] , 2 );
    	}
    	return sqrt(dVec2);
    }
    /*
    		//Einheitsvektor mit Komponenten
    inline double fVecEinheit(double* vector){
    	double dVecLength = fVecLength(vector);
    	vector[0] = vector[0]/dVecLength;
    	vector[1] = vector[1]/dVecLength;
    	vector[2] = vector[2]/dVecLength;
    	cout << vector[0] << endl
    		 << vector[1] << endl
    		 << vector[2] << endl;
    	return fVecLength( vector );
    }
    
    		//Winkelfunktion
    double fVecWinkel(double* vec1, double* vec2){
    	return acos( (fVecSkalar(vec1,vec2))/(fVecLength(vec1)*fVecLength(vec2)));	
    }
    
    */
    


  • Warum sind die Werte dann nicht mehr abrufbar?
    Und dein Code ist nicht sonderlich schön anzusehen, gewöhne dir bitte den ungarischen Stil ab...
    Außerdem hast du ein Problem: du verwendest Arrays fester Länge, lässt den Benutzer aber eine beliebige Anzahl an Werten eingeben, das könnte Probleme geben.
    Und warum sind die Funktionen für das Skalarprodukt und die Länge nicht Teil der Vektor-Klasse?
    Und warum brauchst du überhaupt eine Menü-Klasse, genau für sowas ist eigentlich die Main da...
    Mache dich bitte mal mit Vektoren (da einfach nur als Array dynamisch wachsender Größe) vertraut.
    Und schreibe dann die Vektoren-Klasse um, dass sie kein Array, sondern einen std::vector verwendet, dass macht die Sache für dich einfacher.



  • Vielen Dank für deine schnelle Antwort!

    Warum sind die Werte dann nicht mehr abrufbar?

    Eine sehr gute Frage! Deren Antwort ich leider nicht weiß und mich deswegen entschlossen hatte an dieses Forum zu wenden.

    Außerdem hast du ein Problem: du verwendest Arrays fester Länge, lässt den Benutzer aber eine beliebige Anzahl an Werten eingeben, das könnte Probleme geben.

    double dVec1[3], dVec2[3], dVec3[3];
    Das ist wahr, hatte ich wohl vergessen zu erwähnen:
    Zu Testzwecken habe ich das Array auf 3 gesetzt und nicht mehr umgeändert.

    Der Teil, in dem die Werte in Abhängigkeit der Dimension iDim in das Array eingelesen werden.

    cout<< endl << "Geben Sie Werte ihres ersten Vektors ein: " << endl;
                        for(int i = 0; i < this->iDim ;i++){
                            cout << endl << i+1 << ". Wert: ";
                            cin >> dVec1[i];
                            }
    

    Und dein Code ist nicht sonderlich schön anzusehen, gewöhne dir bitte den ungarischen Stil ab...

    Mhh.. eigentlich finde ich den gar nicht so schlecht 😃
    Man erkennt sofort, um welchen Typ es sich handelt.

    Und warum sind die Funktionen für das Skalarprodukt und die Länge nicht Teil der Vektor-Klasse?
    Und warum brauchst du überhaupt eine Menü-Klasse, genau für sowas ist eigentlich die Main da...

    Ich hatte die Funktionen etc alle bereits fertig und mich entschieden das Ganze als Klasse umzuschreiben.
    Wie ich was mache und wie man es richtig macht ist mir in erster Linie nicht wichtig. Es geht um das eigentliche Problem: Warum werden die Werte von der zuletzt erstellen Instanz Vektor gelöscht, wenn ich eine neue Instanz Vektor erstelle? 😕



  • OK, der Stil ist deine Sache.
    Habe mir das jetzt erst genauer angeguckt
    1. Warum nennst du die Größe iXyz? Warum nicht size oder (meinetwegen auch) iSize?
    2. double dVec[] ist das gleiche wie double *dVec. Du musst erst dynamisch Speicher anfordern.
    3. Die Größe der Set-Funktion wird als Pointer übergeben?! Und dann werden wahllos im Arbeitsspeicher Werte geschrieben?! Es ist ein Wunder, dass dein Programm nicht crasht. Nutze sowas wie:

    void setVector(double vals, std::size_t size)
    {
        dVec = new double [size];
        // mit Werten füllen
    }
    

    4. Deine GetVektor Funktion ist auch Schrott. dVec und this->dVec ist das gleiche. Erst weist du in einer Schleife jedem einzelnen Element den gleichen Wert hinzu (soetwas wie i = i) und dann returnst du ein Element des Vektors hinter dem eigentlcihen Array?! Das ist fatal...

    Entweder du schreibst die Klasse komplett um oder du verwendest std::vector (Link weiter oben), da sparst du dir das.
    Edit: Dann kannst du dir die Klasse aber auch sparen, weil sie dann nur eine Schnittstelle zu std::vector ist und sie direkt so im Menü verwenden oder du musst die Vektor-spezifischen Funktionen ebenfalls da mit reinpacken.


  • Mod

    Nathan schrieb:

    2. double dVec[] ist das gleiche wie double *dVec. Du musst erst dynamisch Speicher anfordern.

    Genaugenommen ist es etwas völlig anderes.

    double dVec[];
    

    deklariert ein Array mit unbestimmter Größe. Und weil das hier eine Definition ist, aber kein Initialisierer angegeben ist, aus dem die Größe hervorgeht, ist diese Definiton schlicht ill-formed. Kann natürlich sein, das ein hirnloser Compiler daraus einen Zeiger macht.



  • Ja? Oh, da hatte ich mich geirrt.
    Ich dachte nur an Funktionsparameter, da wird daraus ein Zeiger.
    Na ja, wieder was gelernt. 🙂


Anmelden zum Antworten