Probleme mit const



  • Hallo zusammen,

    kann mir von Euch jemand sagen, warum folgender Code nicht funktioniert?!

    double calculateSlope(const Point* const p1, const Point* const p2)
    {
    	double retVal = 0;
    	double divisor = p2->GetU() - p1->GetU();
    
    	if (divisor == 0)
    	{
    		if (p2->GetV() >= p1->GetV())
    		{
    			retVal = numeric_limits<double>::infinity();
    		}
    		else
    		{
    			retVal = -1 * numeric_limits<double>::infinity();
    		}
    	}
    	else
    	{
    		retVal = (p2->GetV() - p1->GetV()) / divisor;
    	}
    
    	return retVal;
    }
    

    Point-Datenstruktur:

    #ifndef POINT_H
    #define POINT_H
    
    class Point
    {
    public:
    	Point(int index, double x, double y, double z, double u, double v) : index(index), x(x), y(y), z(z), u(u), v(v), n0(NULL), n1(NULL) { }
    	int GetIndex() { return index; }
    	double GetX() { return x; }
    	double GetY() { return y; }
    	double GetZ() { return z; }
    	double GetU() { return u; }
    	double GetV() { return v; }
    	Point* GetN0() { return n0; }
    	void SetN0(Point* n0) { this->n0 = n0; }
    	Point* GetN1() { return n1; }
    	void SetN1(Point* n1) { this->n1 = n1; }
    private:
    	int index;
    	double x;
    	double y;
    	double z;
    	double u;
    	double v;
    	Point* n0;
    	Point* n1;
    };
    
    #endif
    

    Fehlermeldung beim Compilieren:
    error C2662: 'Point::GetU': this-Zeiger kann nicht von 'const Point' in 'Point &' konvertiert werden
    Durch die Konvertierung gehen Qualifizierer verloren

    Gruß
    Patrick



  • Du mußt die ganzen Getter-Methoden als const deklarieren, damit sie auch für konstante Point-Objekte genutzt werden können (die Funktion calculateSlope() arbeitet mit konstanten Objekten):

    class Point
    {
    public:
        Point(int index, double x, double y, double z, double u, double v) : index(index), x(x), y(y), z(z), u(u), v(v), n0(NULL), n1(NULL) { }
        int GetIndex() /*hier:*/const
        { return index; }
        ...
    };
    

    PS: hast du mal darüber nachgedacht, die Point's per Referenz zu übergeben:

    double calculateSlope(const Point& p1, const Point& p2);
    


  • Danke für die schnelle Antwort. Ich habe schon davon gelesen, dass man besser Referenzen anstelle von Pointer nutzen sollte, allerdings ist mir bisher noch nicht ganz klar warum. Was ist der Vorteil Deines PS?

    Gruß
    Patrick



  • 1. Es ist wesentlich schwieriger, etwas ungültiges zu übergeben, da Du ein Objekt zum übergeben brauchst statt eines Zeigers. Zeiger können schneller mal NULL oder ungültig belegt sein.
    2. Du musst weniger mit dem Sternchen rumhantieren 😉 EDIT: Und Pfeilchen.



  • PACoSys schrieb:

    Was ist der Vorteil Deines PS?

    Kürzer zu schreiben, einfacher zu lesen, sicherer (was passiert, wenn du calculateSlope(irgendwas,NULL); aufrufst?),... - such dir etwas aus 😉



  • Okay habe es gerafft.

    Ein anderes Probleme habe ich noch. Wie müsste man das schreiben?

    void setNextPointAfter(const Point &point, vector<*Point> orderedPoints)
    {
    }
    

    In der Funktion soll dem vector ein neuer Eintrag hinzugefügt werden. Der Aufruf erfolgt über:

    setNextPointAfter(*startPoint, orderedPoints);
    

    wobei orderedPoints ein vector<Point*> ist. Beim Compilieren bekomme ich zwei Fehler:
    1. Für den Aufruf der Funktion: error C2664: 'setNextPointAfter': Konvertierung des Parameters 2 von 'std::vector<_Ty>' in 'std::vector' nicht möglich
    2. Für die Funktion: error C2275: 'Point': Ungültige Verwendung dieses Typs als Ausdruck

    Was ist das Problem?

    Gruß
    Patrick



  • Erstens heißt das vector<Point*>.

    Zweitens: Was soll diese Funktion eigentlich machen?

    Und drittens: vector'en zu kopieren ist aufwendig - den solltest du auch als const-ref übergeben.



  • CStoll schrieb:

    Erstens heißt das vector<Point*>.

    Sorry habe ich übersehen.

    Die Funktion soll rekursiv aufgerufen werden. Der vector soll zum Schluß die Punkte in einer bestimmten Reihenfolge enthalten. Beginnend bei einem Startpunkt soll in der Funktion immer ein Punkt zu dem vector hinzufügt werden und mit diesem die Funktion neu aufgerufen werden.

    Gruß
    Patrick



  • PACoSys schrieb:

    Die Funktion soll rekursiv aufgerufen werden. Der vector soll zum Schluß die Punkte in einer bestimmten Reihenfolge enthalten. Beginnend bei einem Startpunkt soll in der Funktion immer ein Punkt zu dem vector hinzufügt werden und mit diesem die Funktion neu aufgerufen werden.

    Also 'point' ist der Startpunkt und in 'orderedPoints' landen erst seine Nachbarn, dann deren Nachbarn etc, bis die komplette Struktur dort drin steht, richtig? In dem Fall benötigst du sogar eine nicht-konstante Referenz, damit auch das aufrufende Programm etwas davon hat, daß du den vector gefüllt hast.



  • Also so:

    void setNextPointAfter(const Point &point, vector<Point*> &orderedPoints){...}
    

    Sollte man die Referenzen mit einem kleinen r kennzeichnen oder eher wie oben?

    void setNextPointAfter(const Point &rPoint, vector<Point*> &rOrderedPoints){...}
    

    Gruß
    Patrick



  • Das ist letztendlich egal - mach es so, daß du deinen Quelltext lesen kannst (aber bitte konsequent). Für den Compiler ist beides nur ein Name, den er zur Kenntnis nimmt ohne etwas hineinzudeuten.

    (PS: Ich hoffe mal, das endet jetzt nicht in einer Diskussion "Ungarische Notation - Ja oder Nein?")


Log in to reply