2017-02-24 1 views
1

Versuchen, einen Weg zu finden, meine dynamische Umwandlung zu arbeiten, aber ich bekomme Laufzeitfehler. Es springt beim Ausgeben zum else-Anweisungsblockwert (wenn es ein if-Blockwert sein soll, wird aber nicht einmal verwendet, wenn ich es innerhalb der abgeleiteten Klasse aufruft. Es zeigt also den falschen Wert an und verwendet es auch gar nicht in der . Berechnung Warum ist das Danke für die HilfeVerwenden von dynamischer Umwandlung, um unterschiedliche Werte für Variable in abgeleiteter Klasse zurückzugeben

class Package 
{ 
protected: 
    string name_and_address = "?"; 

    double cost = 0.0; 
    double discount = 0.0; 
    double discount_rate = 0.0; 

    bool overnight_delivery = false; 
    bool insured = false; 

    string package_contents = "?"; 

    double shipcost = 0.0; 

public: 
    Package() {}; 
    ~Package() {}; 

protected: 
    virtual double calculate_cost() = 0; 

    class Video_Games {}; //defined the classes 
    class Genius_Phone {}; 
    class Sausage {}; 
    class Albums {}; 

    // here I'm trying to change "shipcost" inside each of the derived classes 
    // to their respective and appropriate dollar values. 
    // However, I am getting a runtime error wherein it will jump DIRECTLY 
    // to the else statement 50.00 value for Video_Games 
    // and not even calculate the value as 50.00. SO it's doubly useless. 
    // It just skips to the else value and doesn't even factor 
    // that into the Video_Games calculation when I try to test it. 
    virtual double shipping_cost() { 
     if (dynamic_cast<Video_Games*>(this)) 
      return 4.99; 
     else if (dynamic_cast<Genius_Phone*>(this)) 
      return 25.00; 
     else if (dynamic_cast<Sausage*>(this)) 
      return 9.00; 
     else 
     { 
      // should be assigned to class Albums, 
      // but is somehow being triggered by class Video_Games. 
      // Not sure why this is. 
      return 50.00; 
     } 
    } 
}; 

class Video_Games :public Package 
{ 
private: 
    int num_games = 0; 

public: 
    Video_Games(string location, int number_of_games, bool express, bool insurance) 
    { 
     num_games = number_of_games; 
     name_and_address = location; 
     overnight_delivery = express; 
     insured = insurance; 

     package_contents = to_string(num_games) + " Video Game(s)"; 

     cost = calculate_cost(); 
     discount = calculate_discount(); 
     shipcost = shipping_cost(); 
    } 

    ~Video_Games() {}; 

protected: 

    double calculate_cost() 
    { 
     cost = num_games * 19.99; 
     // this is where the magic should happen. 
     // shipcost here should be 4.99, but instead it's not even being used here. 
     // In fact - it's empty. I'm not sure why shipcost 
     // when set equal shipping_cost() is not returning that appropriate value. 
     // Very baffling. 
     if (overnight_delivery) { cost += shipcost; } 
     if (insured) { cost *= 1.06; } 

     return cost; 
    } 
}; 
+0

Das liegt daran, dass Sie es falsch machen. Sie sollten sich diese Seite ansehen, um sie zu benutzen: http://en.cppreference.com/w/cpp/language/dynamic_cast – Asesh

+0

Es ist lustig, dass Sie diese Seite verlinkt haben. Ich habe es auf diese Weise versucht, und ich habe das gleiche Endergebnis bekommen. Vielleicht könntest du mir zeigen, wie ich diesen Code auf diese Weise faktorisieren kann? – polymorphism

+3

Nicht verwandt mit der Frage - aber warum verwenden Sie nicht eine Art polymorphe 'GetShippingCost()' Funktion? Es wäre viel besser lesbar und würde dich davon abhalten, diese hässliche Konditionals/'dynamic_cast' Mischung zu haben. – pSoLT

Antwort

5

Das Problem ist, wie Sie die anderen Klassen definiert haben:..

class Package 
{ 
    class Video_Games {}; //defined the classes 
    class Genius_Phone {}; 
    class Sausage {}; 
    class Albums {}; 

innen Package dies sind verschachtelte Typen, Sie haben eine definierte Klasse Package::Video_Games, die keine Basisklassen und keine Mitglieder hat. Die dynamic_cast Ausdrücke verwenden diese Typen, die nicht von Package ableiten:

 if (dynamic_cast<Video_Games*>(this)) 
      return 4.99; 

Namenssuche innerhalb der Package::shipping_cost() Funktion findet den Package::Video_Games-Typ, der die leere Klasse ohne Basisklassen oder Mitglieder. Das Objekt ist niemals dieser Typ, da Package::Video_Games nicht von Package abgeleitet ist, so dass der this Zeiger vom Typ Package* nicht auf ein Objekt vom Typ Package::Video_Games zeigen kann.

Später definieren Sie neue Typen mit den gleichen Namen, dass von Package ableiten:

class Video_Games :public Package 
{ 

Aber dies ist ein neuer Typ. Video_Games ist nicht derselbe Typ wie Package::Video_Games. Wenn Sie ein abgeleitetes Paketobjekt definieren, verwendet es diesen Typ und nicht den Typ, den der Cast verwendet. So werden deine Modelle niemals erfolgreich sein.

Sie müssen die Definitionen der verschachtelten Typen innerhalb Package und bewegen den Körper Ihrer Package::shipping_cost() Funktion außerhalb der Klasse zu entfernen, nachdem alle anderen Typen definiert wurden (so dass der Compiler hat die Definitionen dieser anderen Typen gesehen und weiß, sie sind abgeleitet von Package).

class Package 
{ 
    virtual double shipping_cost(); 
    // ... 
}; 

class Video_Games : public Package 
{ 
    // ... 
}; 

// Now you can define the virtual function: 
double Package::shipping_cost() 
{ 
    if (dynamic_cast<Video_Games*>(this)) 
    // ... 
} 

(Aber wie die Kommentare sagen, das ist eine wirklich schlechte Art und Weise ist eine polymorphe Schnittstelle zu definieren -. Es Niederlagen der ganze Zweck der virtuellen Funktionen)

+0

Danke Jonathan Ich verdaue langsam deine Arbeit und es fängt an, Sinn zu ergeben. Allerdings finde ich Probleme mit der 'shipcost'-Variable, da sie sagt, dass sie jetzt nicht definiert ist. Nicht sicher warum. Ich habe 'shipcost = shipping_cost()' in die von Video_Games abgeleitete Klasse geschrieben, aber es nagt immer noch an meinem Fuß und sagt mir, dass es nicht definiert ist, obwohl ich es so deklariert habe, wie du es in Klasse Package gesagt hast. – polymorphism

+0

Okay, ich spiele Whack-a-Maulwurf gerade mit diesem Programm ... Ich habe es schön kompilieren lassen, und es zeigt die Versandkosten _exactly_ wie ich wollte. Allerdings gibt mir die abgeleitete Video_Games-Klasse ** die Versandkosten von 50,00 berechnet mit der Summe, aber es zeigt 4,99 als die Versandkosten, (und das ist richtig und was es sein sollte, nicht die 50,00, die es ist Verwendung implizit in den Berechnungen) ** .... so jetzt ist mein Problem auf den Kopf gestellt worden. Bevor ich die 50.00 als Versandkosten angezeigt bekam und die 4.99 berechnet. Mein Kopf dreht sich jetzt offiziell. – polymorphism

+0

Tatsächlich werden alle Berechnungen nach Ihrer Methode mit der 50,00 Bewertung der Versandkosten durchgeführt, während die gesamte angezeigte Versandkosten pro abgeleiteter Klasse genau ist. – polymorphism

2

Ironischerweise gegeben Ihren Benutzernamen, du bist fehlende Polymorphie für die korrekte Implementierung. Statt auf Typ wechseln, können Sie die virtuelle Methode aufrufen, und das wird die richtige Version abholen:

class Package { 
public: 
    virtual ~Package(); 
    virtual double shipping_cost() const; 
}; 
class Video_Games : public Package { 
public: 
    double shipping_cost() const override; 
}; 
class Genius_Phone : public Package { 
public: 
    double shipping_cost() const override; 
}; 
class Sausage : public Package { 
public: 
    double shipping_cost() const override; 
}; 

Package::~Package() {} 

double Package::shipping_cost() const 
{ 
    // Default implementation - may be overridden in subclasses 
    return 50.00; 
} 

double Video_Games::shipping_cost() const 
{ 
    return 4.99; 
} 

double Genius_Phone::shipping_cost() const 
{ 
    return 25.99; 
} 

double Sausage::shipping_cost() const 
{ 
    return 9.00; 
} 

ich auch, dass die Verwendung Gleitkommatypen für monetäre Werte, die Sie führen in Schwierigkeiten warnen sollte - eine Suche of Stack Overflow sollte Antworten finden, die erklären warum.

+2

Sie vermissen die Erbschaft. – Jarod42

+0

Ganz richtig - dank @Lightness für die Reparatur in meinem Namen. –

+1

Die gute Nachricht ist, dass ich die Methoden "override" deklariert habe, so dass der Compiler Sie über den Fehler informieren würde. :-) –

Verwandte Themen