//Illustrating *inheritance* and  *abstract classes*
#include <iostream>
#include <string>

//An example program that asks for a potential customer for the name
//of a car, and prints out a sales spiel

class cars{ //An ABSTRACT CLASS -- cannot instantiate
public:
  cars(string n ="noName", int c = 0) : name(n), msrp(c){}

  // What is the cost to consumer?  Different cars have different discount policies
  virtual int   quotedCost() = 0;

  //how long to get from speed s1 to speed s2? -- car-dependent
  virtual float accelTime(int s1, int s2)  = 0;

  void salesSpiel(){//Essentially the same for all cars
    cout<<"The " << name <<" costs $" << msrp; 
    cout<< ", but for you its only $" << quotedCost() <<endl;
    cout <<"It can do 0 to 60 in " << accelTime(0,60)<< " secs, and come ";
    cout <<"to a complete halt again in " << accelTime(60,0)<< " secs.\n\n";
  }
protected:
  string name;
  int msrp;  // By US law, every car must have an MSRP
};
  
class yugo: public cars{ // Both abstract methods are defined here
public:
  yugo(): cars("Yugo", 6999){}
  int quotedCost(){return (msrp - 2000);} // a 20K discount
  float accelTime(int s1, int s2){
    if (s1 < s2) //accelerating
      return (s2 - s1)/2.0;
    return (s1 - s2)/10.0;
  }
};

class ferrari: public cars{ // Both abstract methods are defined here
public:
  ferrari(): cars("Ferrari", 225000){}
  int quotedCost(){return (int) (msrp * 0.90);} // a 10 percent discount
  float accelTime(int s1, int s2){
    if (s1 < s2) //accelerating
      return (s2 - s1)/12.0;
    return (s1 - s2)/25.0;
  }
};

class suv: public cars{ //One abstract method not defined; therefore,
 //class remains abstract
public:
  suv(string s="noSuv", int n=0, int m=0): cars(s,n), mileage(m){}
  int quotedCost(){return (msrp - 2399);}//a 2399 dollar discount on all SUV's
private:
  int mileage; // another relevant fact about SUV's
};

class explorer: public suv{ //derived from suv, which is derived from cars
public:
  explorer(): suv("Explorer", 30000, 17){}
  float accelTime(int s1, int s2){
    if (s1 < s2) //accelerating
      return (s2 - s1)/5.5;
    return (s1 - s2)/15.0;
  }
};

int main(){
  cars * carPtr;
  string s;
  cout <<"\nWelcome to Clunky Wheels!  What car are you interested in? ";
    cin >> s;
  while ((s == "Yugo") || (s == "Ferrari") || (s == "Explorer")){
    if (s == "Yugo") carPtr = new yugo;
    else if  (s == "Ferrari") carPtr = new ferrari;
    else if  (s == "Explorer") carPtr = new explorer;
    //else carPtr = new suv; -- error!
    // else carPtr = new cars; -- illegal: would generate compiler error
    carPtr->salesSpiel();
    cout <<"What car are you interested in? ";
    cin >> s;
  }
}
  
