// meal3.cxx - third attempt at OOP meal pricing program
#include <stream.h>

enum ENTREE {Steak,Fish};
enum DESSERT {Pie,Cake,Jello};
enum APPETIZER {Melon,ShrimpCocktail};

class Dessert   // An abstract class
                // - never instantiated by itself
    { 
public:
    virtual double cost() = 0; // pure virtual ==> 
                               // abstract class
    virtual double discount() { return .75; } // 25% off
    virtual const char* text() = 0;
    };

class Jello_obj : public Dessert
    {
public:
    double cost() {return .60;}
    const char* text() { return "Jello ";}
    };

class Pie_obj : public Dessert
    {
public:
    double cost() {return  1.50;}
    double discount() { return 1.00; } // no discount
    const char* text() { return "Pie ";}
    };

class Cake_obj : public Dessert
    {
public:
    double cost() {return  1.00;}
    const char* text() { return "Cake ";}
    };

class Entree
    {
public:
    virtual double cost() = 0;
    virtual const char* text() = 0;
    };

class Fish_obj : public Entree
    {
public:
    double cost() {return 4.00;}
    const char* text() { return "Fish ";}
    };

class Steak_obj : public Entree
    {
public:
    double cost() {return 7.50;}
    const char* text() { return "Steak ";}
    };

class Appetizer
    {
public:
    virtual double cost()  = 0;
    virtual const char* text() = 0;
    };

class Cocktail_obj : public Appetizer
    {
public:
    double cost() { return  2.00;}
    const char* text() { return "Cocktail ";}
    };

class Melon_obj : public Appetizer
    {
public:
    double cost() { return .85;}
    const char* text() { return "Melon ";}
    };

class Meal 
    {
    Appetizer *a;
    Entree *e;
    Dessert *d;
public:
    Meal(APPETIZER=Melon,ENTREE=Fish,DESSERT=Jello);
    ~Meal();
    double cost();
    void print();
    };

//-------------------------------------------
// class member function definitions

double Meal::cost() {return d->cost()*d->discount() +
         a->cost() + e->cost(); }

Meal::Meal(APPETIZER aval,ENTREE eval,DESSERT dval)
    {
    if ( dval == Jello ) d = new Jello_obj;
    else if ( dval == Pie ) d = new Pie_obj;
    else d = new Cake_obj;
    if ( eval == Steak ) e = new Steak_obj;
    else e = new Fish_obj;
    if ( aval == Melon ) a = new Melon_obj;
    else a = new Cocktail_obj;
    }

Meal::~Meal() { delete a; delete e; delete d; }

void Meal::print()
    {
    cout << a->text() << e->text() << d->text() <<
        ", Meal cost = " << a->cost() + e->cost() + 
        d->cost()*d->discount() << "\n";
    }
//--------------------------------------------
main()
    {
    Meal m1(Melon,Fish,Jello);
    Meal m2(Melon,Steak,Pie);
    Meal m3(ShrimpCocktail,Steak,Cake);
    m1.print(); m2.print(); m3.print();
    }
// ---- sample output below -----

Melon Fish Jello , Meal cost = 5.3
Melon Steak Pie , Meal cost = 9.85
Cocktail Steak Cake , Meal cost = 10.25
