2016-12-09 11 views
0

erhalten Ich bekomme Segmentierung Fehler für diesen kurzen Code und ich bin nicht in der Lage, herauszufinden, warum.Segmentierungsfehler beim Aufruf einer virtuellen Funktion an einer abgeleiteten Klasse

class XorY { 
public: 
    virtual void set_cost(double& cost){} 

}; 
class X_based:public XorY { 
public: 
    X_based(int _x):x(_x){} 
    void set_cost(double& cost) 
    { 
     cost=cost*(100-x)/100; 
    } 
    int x; 
}; 
class Y_based:public XorY 
{  
    public: 
     Y_based(){} 
     Y_based(int _y): y(_y){} 
     void set_cost(double& cost){ 
      cost=cost-y; 
     } 
     int y; 
}; 


int main(){ 
    double a=2; 
    XorY* type; 
    Y_based* ptr; 
    *ptr=Y_based(3); 
    type=ptr; 
    type->set_cost(a); 
} 

Es scheint, dass es ein Fehler mit dieser Linie

*ptr=Y_based(3); 

Wenn ich es ändern zu

ptr=&Y_based(3); 

ich diesen Compiler-Fehler erhalten:

taking address of temporary [-fpermissive] 

Danke voraus.

+3

Hinweis: worauf zeigt 'Ptr', wenn Sie dies tun? '* ptr = Y_basiert (3);'. – juanchopanza

+0

Ich versuche, es auf ein Objekt von Y_based Klasse zu zeigen. Ich rufe es Konstruktor, dies zu tun –

+2

@ Ghazal.S, Dereferenzierung eines Zeigers, der nicht initialisiert wurde oder auf ein gültiges Objekt verweist, führt zu undefiniert Verhalten. In deinem Fall ist 'ptr' ein solcher Zeiger. –

Antwort

1

Du hast Recht, die Linie

*ptr=Y_based(3); 

ist falsch. Ich nehme an, Sie meinten, dass der Zeiger ptr nach diesem Vorgang auf das neue Objekt vom Typ Y_based zeigen sollte.

Hovewer, die Bedeutung dieser Zeile ist anders.

Zuerst wird der rechte Teil (Y_based(3)) berechnet. Es ist ein Objekt vom Typ Y_based mit _y Feld gleich 3. Danach wird der linke Teil (*ptr) berechnet. Es ist das Objekt, auf das der Zeiger ptr zeigt, und es ist nicht definiert, da der Zeiger nicht initialisiert wurde. Wenn der Zeiger initialisiert wurde, würde danach der Wert des rechten Teils dem Wert des linken Teils zugewiesen werden. Das heißt, das Objekt, auf das von ptr gezeigt wird, würde sich ändern, nicht der Zeiger selbst.

Ihr erwünschtes Verhalten kann durch Schreiben

ptr = new Y_based(3); 

hier der linken Teil erreicht werden, die zugeordnet ist, ist es nicht das Objekt von ptr spitz, aber ptr selbst, und den rechten Teil ist ein Zeiger auf einem neu erstelltes Objekt vom Typ Y_based.

Da auch das Objekt vom Typ Y_based vom new Schlüsselwort erstellt wurde, wird es nicht zerstört werden, nachdem Sie den Block verlassen, und Sie sollten manuell darum kümmern, delete auf einer Linie mit dem Sie nicht brauchen, das Objekt mehr. Um richtig ein Objekt durch den Zeiger auf die Basisklasse zu zerstören, sollten Sie auch einen virtuellen Destruktor in der Basisklasse definieren:

class XorY { 
public: 
    virtual void set_cost(double& cost){} 
    virtual ~XorY() = default; 
}; 

Wenn Sie nicht wollen, mit all diesen Sachen kümmern, müssen aber noch haben ein polymorphes Verhalten, können Sie eine Referenz anstelle eines Zeigers verwenden:

int main(){ 
    double a=2; 
    Y_based& ptr = Y_based(3); 
    XorY& type = ptr; 
    type.set_cost(a); 
} 
+0

Ja jetzt bekomme ich es.Vielen Dank :) @ alexeykuzmin0 –

Verwandte Themen