Funktionen



  • Folgende Funktion bei mir will der Compiler nicht kompilieren:

    float Distance(float x1, float y1, float z1, float x2, float y2, float z2) 
    {
    	return (float) sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));
    }
    
    error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.
    1>c:\dokumente und einstellungen\theo\eigene dateien\visual studio 2008\projects\mydll\main.cpp(222) : error C2059: Syntaxfehler: 'Konstante'
    1>c:\dokumente und einstellungen\theo\eigene dateien\visual studio 2008\projects\mydll\main.cpp(222) : error C2143: Syntaxfehler: Es fehlt ')' vor ';'
    1>c:\dokumente und einstellungen\theo\eigene dateien\visual studio 2008\projects\mydll\main.cpp(222) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.
    1>c:\dokumente und einstellungen\theo\eigene dateien\visual studio 2008\projects\mydll\main.cpp(222) : error C2078: Zu viele Initialisierungen
    1>c:\dokumente und einstellungen\theo\eigene dateien\visual studio 2008\projects\mydll\main.cpp(222) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.
    1>c:\dokumente und einstellungen\theo\eigene dateien\visual studio 2008\projects\mydll\main.cpp(222) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.
    1>c:\dokumente und einstellungen\theo\eigene dateien\visual studio 2008\projects\mydll\main.cpp(222) : error C2374: 'PI': Neudefinition; Mehrfachinitialisierung
    

    Kann mir wer helfen ? 🙂

    Vielen Dank
    Umsteiger



  • math-Header eingebunden?



  • PI definierst du doppelt. Vielleicht wurde der Header mehrfach eingebunden? In dem Fall helfen Include Guards (oder ein #pragma once am Anfang des Headers).



  • btw:

    float Distance(float x1, float y1, float z1, float x2, float y2, float z2) 
    { 
        return (float) sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2)); 
    } 
    
    //=>
    
    float Distance(float x1, float y1, float z1, float x2, float y2, float z2) 
    {
        x1 -= x2;
        y1 -= y2;
        z1 -= z2;
        const float distance_square = x1*x1 + y1*y1 + z1*z1;
        return static_cast <float> sqrt(distance_square); 
    }
    

    bb



  • unskilled schrieb:

    return static_cast <float> sqrt(distance_square);
    

    Der Cast ist hier unnötig.

    Um das Ganze etwas übersichtlicher zu machen, könnte man eine Klasse/Struktur für Punkte machen, die Operatoren überladen und eine Funktion für die Norm schreiben. Geht hier vielleicht etwas zu weit, aber es ist doch schön, eine solche Funktion zu haben: 😉

    float Distance(const Point& Left, const Point& Right)
    {
        return Norm(Left - Right);
    }
    


  • Nexus schrieb:

    float Distance(const Point& Left, const Point& Right)
    {
        return Norm(Left - Right);
    }
    

    Was soll dein Norm machen?

    wenn schon dann find ich das toller ^^

    float Distance(Point Left, const Point& Right)
    {
        Left -= Right;
        return Dotproduct(Left, Left); //Kreuzprodukt mit sich selbst
    }
    

    bb



  • unskilled schrieb:

    Was soll dein Norm machen?

    Die Länge eines Vektors zurückgeben. 😉

    unskilled schrieb:

    wenn schon dann find ich das toller ^^

    float Distance(Point Left, const Point& Right)
    {
        Left -= Right;
        return Dotproduct(Left, Left); //Kreuzprodukt mit sich selbst
    }
    

    Hm, mir gefällt nur schon die Signatur nicht. Ein Parameter als Kopie und ein anderer als Const-Referenz, obwohl beide gleichwertig sind - naja. Wieso beharrst du eigentlich so auf deinen arithmetischen Zuweisungsoperatoren? 🙂

    Zudem müsstest du noch die Wurzel aus dem Skalarprodukt ziehen...



  • Nexus schrieb:

    Hm, mir gefällt nur schon die Signatur nicht. Ein Parameter als Kopie und ein anderer als Const-Referenz, obwohl beide gleichwertig sind - naja.

    Es ist nun mal unsinnig beide als referenz zu übernehmen und dafür nen neues objekt zu erzeugen - die signatur ist nun mal so... ^^

    Nexus schrieb:

    Wieso beharrst du eigentlich so auf deinen arithmetischen Zuweisungsoperatoren? 🙂

    Weils effektiver ist!? ^^
    Und keinerlei Nachteile hat außer vll die ungewohnte Signatur ^^

    Nexus schrieb:

    Zudem müsstest du noch die Wurzel aus dem Skalarprodukt ziehen...

    Verdammt -.- Wie peinlich - mehr Fehler konnte man ja gar nicht mehr da reinmachen ^^

    bb



  • unskilled schrieb:

    Nexus schrieb:

    Hm, mir gefällt nur schon die Signatur nicht. Ein Parameter als Kopie und ein anderer als Const-Referenz, obwohl beide gleichwertig sind - naja.

    Es ist nun mal unsinnig beide als referenz zu übernehmen und dafür nen neues objekt zu erzeugen - die signatur ist nun mal so... ^^

    Finde ich auch, dass es nun mal Geschmackssache ist. Ist ja dasselbe, wie beim swap, ob da auch gleich per Kopie übergeben werden soll oder intern erzeugt.
    Soll jeder so machen, wie will (oder vorgegeben).



  • Danke für die Zustimmung, aber:

    drakon schrieb:

    Ist ja dasselbe, wie beim swap, ob da auch gleich per Kopie übergeben werden soll oder intern erzeugt.

    wie soll nen swap mit ner Kopie des/der Werte(s) funktionieren? Oo

    bb



  • unskilled schrieb:

    Danke für die Zustimmung, aber:

    drakon schrieb:

    Ist ja dasselbe, wie beim swap, ob da auch gleich per Kopie übergeben werden soll oder intern erzeugt.

    wie soll nen swap mit ner Kopie des/der Werte(s) funktionieren? Oo

    bb

    Sorry, meinte den =-Operator. Dort wird ja normalerweise eine cont Ref. übergeben und dann ein lokales Objekt damit erzeugt und geswapt. Und da kann man auch direkt die Übergabe per Kopie machen und dann mit dem swapen.



  • drakon schrieb:

    Sorry, meinte den =-Operator. Dort wird ja normalerweise eine cont Ref. übergeben und dann ein lokales Objekt damit erzeugt und geswapt. Und da kann man auch direkt die Übergabe per Kopie machen und dann mit dem swapen.

    Macht ihr das wirklich immer so?
    Was spricht dagegen, es nicht über den swap weg zu implementieren?

    bb



  • unskilled schrieb:

    drakon schrieb:

    Sorry, meinte den =-Operator. Dort wird ja normalerweise eine cont Ref. übergeben und dann ein lokales Objekt damit erzeugt und geswapt. Und da kann man auch direkt die Übergabe per Kopie machen und dann mit dem swapen.

    Macht ihr das wirklich immer so?
    Was spricht dagegen, es nicht über den swap weg zu implementieren?

    bb

    Wie gesagt. Geschmackssache (abgesehen von Optimierungen). Ich persönlich mache es eigentlich so, dass ich eine lokale Kopie erzeuge und dann damit swape.
    Afaik kommt schlussendlich sowieso das gleiche raus nach dem compilen. (zumindest bei modernen Compilern).



  • unskilled schrieb:

    Was spricht dagegen, es nicht über den swap weg zu implementieren?

    Was spricht denn dafür, Copy-Konstruktor und Destruktor doppelt zu implementieren?



  • Wieso lautet dein Benutzername theo?



  • fdsa schrieb:

    unskilled schrieb:

    Was spricht dagegen, es nicht über den swap weg zu implementieren?

    Was spricht denn dafür, Copy-Konstruktor und Destruktor doppelt zu implementieren?

    1. verschrieben 😛 DTor->CTor nehm ich mal an ^^
    2. war die ganze zeit von der swap fkt ausgegangen die man idR für die nachfolgende spezialisierung von std::swap implementiert - aber ihr nennt die init-fkt ja auch immer swap ^^

    bb



  • unskilled schrieb:

    1. verschrieben 😛 DTor->CTor nehm ich mal an ^^

    Nein, ich hab mich mich verschrieben. Wenn man den Zuweisungs-Operator nicht mit copy&swap macht, implementiert man nochmal genau das, was man in Destruktor und Copy-Konstruktor schonmal gemacht hat.



  • fdsa schrieb:

    unskilled schrieb:

    1. verschrieben 😛 DTor->CTor nehm ich mal an ^^

    Nein, ich hab mich mich verschrieben. Wenn man den Zuweisungs-Operator nicht mit copy&swap macht, implementiert man nochmal genau das, was man in Destruktor und Copy-Konstruktor schonmal gemacht hat.

    Also ich habe im =-Operator und üblicherweise 3 Zeilen:

    X::operator = (const X &rhs)
    {
       Destruct();
       Init(/*ggf parameter*/);
       return *this;
    }
    
    X::X (const X &rhs)
    {
       Init(/*ggf parameter*/);
    }
    
    X::~X () throw()
    {
       Destruct();
    }
    

    Der einzige Unterschied ist eben, dass die Zuweisung bei einer Exception das alte Objekt löscht und das neue dann halt noch nicht konstruiert ist - aber imho ist das kein Nachteil...

    bb



  • unskilled schrieb:

    Also ich habe im =-Operator und üblicherweise 3 Zeilen:

    X::operator = (const X &rhs)
    {
       Destruct();
       Init(/*ggf parameter*/);
       return *this;
    }
    
    X::X (const X &rhs)
    {
       Init(/*ggf parameter*/);
    }
    
    X::~X () throw()
    {
       Destruct();
    }
    

    Der einzige Unterschied ist eben, dass die Zuweisung bei einer Exception das alte Objekt löscht und das neue dann halt noch nicht konstruiert ist - aber imho ist das kein Nachteil...

    Nein Nein Nein Nein.
    Leben wir noch im Jahre 1998?

    Der op= sieht immer so aus:

    T const& operator=(T const& other) {
      T temp(other);
      swap(temp);
      return *this;
    }
    

    Keine Exception Sicherheit ist immer ein Nachteil. Wenn der op= naehmlich wirft ist dein Objekt kaputt. Alle Daten sind verloren. Das ist schlecht. Sehr schlecht sogar. Deshalb hat Gott uns Transaktionen geschenkt und Stroustrup hat sie uns in Form von Copy & Swap ermoeglicht.

    PS:
    die Init Funktion ist ja richtig 1998...



  • Wenn eine exception beim =-op geworfen wird, kannst du iA eh nicht darauf reagieren... (oder fällt dir nen sinnvolles Bsp ein?)
    Und warum soll eine Zuweisung 3mal so lange brauchen wie man sie normalerweise implementieren könnte?

    die Init Funktion ist ja richtig 1998...

    Sie hilft einfach mal die Übersicht zu wahren und nicht zu letzt Code-Duplikationen zu vermeiden. Ich weiß ja nicht, was du bis zum nächsten Standard machst - aber ich kann bis dahin keinen CTor in nem anderen aufrufen - und deshalb bleibt nun mal nur den Ausweg mit Init()

    bb


Anmelden zum Antworten