[gelöst]Bezeichner nicht definiert?!



  • @Daniel-l06

    Ja, sollte

    Weil ein * davor steht?



  • Ich verstehe deine Antwort nicht nicht wirklich?
    Programmieren und C++ ist echt sehr neu für mich, also frag ich lieber nach bevor ich etwas falsch verstanden habe?



  • @manni66 wollte wissen, warum da ein * steht. Wäre nicht logischer, wenn da & stehen würde? Und warum nicht einfach nur "funktion3" ohne * und &? Denk mal darüber nach bzw gucke nach. C++ konvertiert implizit Funktionen zu Funktionspointern. (siehe auch Abschnitt "Pointers to functions" hier: https://en.cppreference.com/w/cpp/language/pointer)

    Das sollte allerdings nicht zu deinem Fehler führen.

    Was mich an deiner Aussage noch stutzig mach, ist:

    In meiner Headerdatei ist die Methode mit

    friend CMyMatrix jacobi(CMyVektor x, CMyVektor(*funktion)(CMyVektor x));
    

    implementiert.

    Wie man an dem Semikolon sieht, ist diese Funktion dort nicht implementiert, sondern dort ist lediglich eine Deklaration zu finden. Die Implementation ist offenbar anderswo. Existiert die überhaupt? Das würde dann auch die Fehlermeldung erklären.

    Ein Minimalbeispiel, was man aus deinen Angaben machen kann, kompiliert:

    struct CMyVektor {};
    struct CMyMatrix {
        // ist jabobi Freund der Matrix oder des Vektors? Und ist Freundschaft überhaupt nötig?
        friend CMyMatrix jacobi(CMyVektor x,
                                CMyVektor(*funktion)(CMyVektor x));
    
    };
    
    // irgendwo muss das Dingen auch definiert sein
    CMyMatrix jacobi(CMyVektor x, CMyVektor(*funktion)(CMyVektor x)) {
        return {};
    }
    
    CMyVektor funktion3(CMyVektor x) { return x; }
    
    int main() {
        CMyVektor wert;
        auto jacobiTest = jacobi(wert, funktion3);
    }
    


  • @wob Oh sorry, das hab ich nicht erwähnt, die Implementierung ist tatsächlich wo anders. Die ist in der .cpp und gibt mir eine Matrix zurück.

    In der Aufgabenstellung ist ein * vorgeben, deswegen bin ich nicht ganz sicher ob ich da einfach etwas ändern darf.



  • @Daniel-l06 da deine Antworten immer nur aus Ausflüchten bestehen, wirst du dann wohl selbst klarkommen müssen.



  • In welcher Datei rufst du denn

     jacobiTest = jacobi(wert, *funktion3);
    

    auf?
    Hast du dort die Headerdatei, in der jacobi deklariert ist, eingebunden?

    Die friend-Deklaration besagt ja nur, daß diese Funktion auf alle (also auch private) Member der umgebenen Klasse zugreifen darf - ob das hier überhaupt benötigt wird, ist aber eine andere Frage.



  • @Daniel-l06 Der Trick ist, soviel Code zu posten, dass der den Fehler 1:1 reproduziert, wenn ich den selbst compiliere. Am liebsten so, dass man den in einen online compiler schieben kann und nicht noch mit mehreren Dateien rum hantieren muss.



  • @Th69 Die wird in der main aufgerufen. Bei mir sieht es so aus, dass ich die 2 Klassen Vektor und Matrix habe, die jeweils in eine Headerdatei und .cpp aufgeteilt sind. Und dann habe ich eine Main in der ich dann die nötigen Verfahren und aufrufe drinnen habe. Die Headerdatei ist mit eingebunden.

    @Schlangenmensch Also eig wollte ich darauf verzichten, weil mir das ein wenig peinlich ist :'D Die meisten werden meinen Code bestimmt sehr unsauber finden aber gut in der .h ist wie erwähnt die

    	friend CMyMatrix jacobi(CMyVektor x, CMyVektor(*funktion)(CMyVektor x));
    

    In der .cpp ist dann die Implementierung:

    CMyMatrix jacobi(CMyVektor x, CMyVektor(*funktion)(CMyVektor x))
    {
    	double h = 10e-4;
    
    	CMyMatrix jacobiM;
    	jacobiM.createMatrix(x.getDimension(), funktion(x).getDimension());
    
    	for (int i = 0; i < funktion(x).getDimension(); i++)	//Matrix N Dimension
    	{
    		for (int j = 0; j < x.getDimension(); j++)			//Matrix M Dimension
    		{
    			CMyVektor temph;
    			temph.createV(x.getDimension());
    			for (int g = 0; g < x.getDimension(); g++)			
    			{
    				temph.setComp(g, x.getComp(g));
    			}
    			double hwert = temph.getComp(i + 1) + h;
    			temph.setComp(i + 1, hwert);									
    																		
    			jacobiM.setComp(j, i, (((funktion(temph).getComp(i)) - (funktion(x).getComp(i)))) / h);
    
    		}
    	}
    	return jacobiM;
    }
    

    Ob dann am Ende die richtige Jacobi Matrix bei raus kommt, sei erstmal dahin gestellt.
    In meiner main ist dann die bereits gepostete Funktion und in der main() wird das alles wie folgt aufgerufen:

    	CMyVektor wert;
    	wert.createV(4);
    	wert.setComp(1, 1);
    	wert.setComp(2, 2);
    	wert.setComp(3, 0);
    	wert.setComp(4, 3);
    	CMyMatrix jacobiTest;
    	jacobiTest.createMatrix(4, 3);
    	jacobiTest.getMatrix();
    	jacobiTest = jacobi(wert, *funktion3);
    
    

    wobei wert der Vektor ist, mit dem das Verfahren an der funktion3 getestet werden soll.

    Grüße
    Daniel



  • Wie ich schon schrieb, reicht die friend-Deklaration alleine nicht aus, um die Funktion außerhalb der Klasse aufrufen zu können.
    Du benötigst noch

    CMyMatrix jacobi(CMyVektor x, CMyVektor(*funktion)(CMyVektor x));
    

    außerhalb der Klassendeklaration.



  • @Daniel-l06 sagte in Bezeichner nicht definiert?!:

    @Schlangenmensch Also eig wollte ich darauf verzichten, weil mir das ein wenig peinlich ist :'D Die meisten werden meinen Code bestimmt sehr unsauber finden aber gut in der .h ist wie erwähnt die

    	friend CMyMatrix jacobi(CMyVektor x, CMyVektor(*funktion)(CMyVektor x));
    

    In der .cpp ist dann die Implementierung:

    CMyMatrix jacobi(CMyVektor x, CMyVektor(*funktion)(CMyVektor x))
    {
    	double h = 10e-4;
    
    	CMyMatrix jacobiM;
    	jacobiM.createMatrix(x.getDimension(), funktion(x).getDimension());
    
    	for (int i = 0; i < funktion(x).getDimension(); i++)	//Matrix N Dimension
    	{
    		for (int j = 0; j < x.getDimension(); j++)			//Matrix M Dimension
    		{
    			CMyVektor temph;
    			temph.createV(x.getDimension());
    			for (int g = 0; g < x.getDimension(); g++)			
    			{
    				temph.setComp(g, x.getComp(g));
    			}
    			double hwert = temph.getComp(i + 1) + h;
    			temph.setComp(i + 1, hwert);									
    																		
    			jacobiM.setComp(j, i, (((funktion(temph).getComp(i)) - (funktion(x).getComp(i)))) / h);
    
    		}
    	}
    	return jacobiM;
    }
    

    Ob dann am Ende die richtige Jacobi Matrix bei raus kommt, sei erstmal dahin gestellt.
    In meiner main ist dann die bereits gepostete Funktion und in der main() wird das alles wie folgt aufgerufen:

    	CMyVektor wert;
    	wert.createV(4);
    	wert.setComp(1, 1);
    	wert.setComp(2, 2);
    	wert.setComp(3, 0);
    	wert.setComp(4, 3);
    	CMyMatrix jacobiTest;
    	jacobiTest.createMatrix(4, 3);
    	jacobiTest.getMatrix();
    	jacobiTest = jacobi(wert, *funktion3);
    
    

    wobei wert der Vektor ist, mit dem das Verfahren an der funktion3 getestet werden soll.

    Und du meinst dass reicht jetzt? Was glaubst du passiert wenn ich verduche die drei Text-Stücke in je ein File zu speichern und das dann zu kompilieren?



  • @hustbaer Okay, ich hab halt in den Richtlinien für Hilfefragen gelesen dass man möglichst wenig Code posten sollte um keinen damit zu erschlagen. Dachte auch, dass ich das nötigste gepostet habe, sorry wenns nicht der Fall war. Das Problem hat sich damit aber auch erledigt.
    Die Antwort von @Th69 hat geholfen. Danke dafür! Ich verstehe nur nicht ganz warum das so ist. Ich hab die Zeile hat nochmal in meine main geschrieben und dann hat es funktioniert. Das seltsame ist nur, dass ich das mit der Funktion um den Gradienten berechnen zu können nicht machen musste. Ich werde dann morgen den Tutor/Prof mal fragen.
    Danke euch für die Hilfe!



  • @Daniel-l06 sagte in [gelöst]Bezeichner nicht definiert?!:

    Das seltsame ist nur, dass ich das mit der Funktion um den Gradienten berechnen zu können nicht machen musste.

    Na, die ist doch eine Methode Deiner Vectorklasse, schreibst Du oben. Die DeinVector.h hast Du sicher eingebunden, sonst könntest Du ja die ganze Klasse nicht benutzen.
    Deine jacobi - Funktion ist aber eine freie Funktion und muss natürlich deklariert werden, um benutzt werden zu können ....
    Zu der cpp-Datei, in der die Funktion definiert ist, gehört doch sicher auch eine h - Datei, und da hinein gehört die Deklaration.



  • @Belli Aber genau so hab ich es auch. Ich habe die jacobi - Funktion in der Matrix.h deklariert und in der Matrix.cpp definiert. Genau so hab ich es auch mit der gradient - Funktion meiner Vektor klasse gemacht. In meiner Main binde ich dann beide ein, Vektor.h sowie Matrix.h und dennoch kann ich gradient(..., ...) aufrufen ohne Probleme aber für meine jacobi(..., ...) muss ich in meiner main nochmal die Deklaration machen wie es mir Th69 geschrieben hat.
    Ich hab also in beiden Fällen alles identisch gemacht und dennoch brauch jacobi diese Zeile Code mehr um zu funktionieren.



  • Dann hättest Du in der main.cpp die Deklaration zweimal ... ?
    Das kann ich nicht glauben.
    Wie oben schon gesagt wurde, das hier:

    friend CMyMatrix jacobi(CMyVektor x, CMyVektor(*funktion)(CMyVektor x));
    

    ist keine Funktionsdeklaration.



  • @Daniel-l06
    Naja es ist eben nicht das selbe.

    Ich vermute mal es liegt daran:

    class Vector {
    public:
        friend void vecFriend(Vector const& vec) {
        }
    };
    
    class Matrix {
    public:
        friend void matrixFriend(Vector const& vec) {
        }
    };
    
    int main() {
        Vector vec;
        vecFriend(vec); // geht
        matrixFriend(vec); // geht nicht
        // und
        auto x = &vecFriend; // geht nicht
        auto y = &matrixFriend; // geht nicht
    }
    

    Grund: eine "friend declaration" einer Funktion ist nicht das selbe wie eine Deklaration der Funktion im umgebenden Namespace - egal ob die Funktion dabei auch implementiert wird oder nicht. Eine normale Deklaration ... naja deklariert die Funktion eben in dem Namespace wo sie erfolgt. D.h. die kann dann in diesem Namespace ganz normal gefunden werden.

    Eine "friend declaration" einer Funktion ermöglicht allerdings NUR das Auffinden der Funktion über ADL (=argument dependent lookup aka. Koenig lookup) -- und das auch nur wenn eines der Argumente genau die Klasse ist in der die "friend declaration" auftaucht (bzw. eine davon abgeleitete Klasse) -- es reicht NICHT wenn eines der Argumente im selben Namespace ist wie die Klasse in der die "friend declaration" steht!

    Beim Aufruf von vecFriend funktioniert das, weil das erste und einzige Argument ein Vector ist. D.h. hier findet ADL für Vector statt, und das findet dann vecFriend weil vecFriend ja ein friend von Vector ist.

    Beim Aufruf von matrixFriend geht es nicht, weil das erste und einzige Argument wieder ein Vector ist. D.h. es findet wieder ADL für Vector statt. Das findet aber nichts, denn: matrixFriend lebt zwar im selben Namespace wie Vector, aber es ist lediglich über eine "friend declaration" bekannt gemacht worden -- und diese "friend declaration" steht nicht in Vector. Also wird matrixFriend über ADL für Vector nicht gefunden und du bekommst einen Fehler.

    Und die beiden Zeilen

        auto x = &vecFriend; // geht nicht
        auto y = &matrixFriend; // geht nicht
    

    demonstrieren dass keine der beiden Funktionen ganz ohne ADL gefunden werden.

    Die Lösung ist die Funktionen nochmal ausserhalb der Klasse zu deklarieren. So wie @Th69 dir das vorgeschlagen hat.

    Ich hab die Zeile hat nochmal in meine main geschrieben und dann hat es funktioniert.

    Du solltest die Zeile nicht "in deine main" schreiben (was übrigens zweideutig ist, du könntest dein main.cpp File oder deine main Funktion meinen). Sondern besser in Matrix.h direkt hinter die Definition der CMyMatrix Klasse.



  • @hustbaer Ah super, das hat mir sehr weiter geholfen! Der Tutor gestern konnte mir leider nicht erklären warum das so war, hat mir aber auch vorgeschlagen die Funktion einfach nochmal direkt hinter der .h zu deklarieren.
    Daher vielen lieben Dank für deine ausführliche Erklärung, hätte sonst nochmal den Kontakt zum Professor gesucht :'D

    Grüße
    Daniel


Anmelden zum Antworten