0

I have a file that I am reading the type of object to create, the amount, and the price. I have verified that the file is being read correctly and the values are being place in the variables type, quantity, and price, however the program gets to the first candy constructor in Checkout.cpp and stops and exits before creating the object. The Candy and Cookie Class inherit from a DessertItem base class, and the vector "desserts" is of type DessertItem.

Checkout.h

class Checkout{

private:
    std::vector<DessertItem*> dessertList;
    std::string fileToOpen;
    int type;
    double quantity;
    double price;

public:
    //constructor
    Checkout(std::string);
    //read file
    std::ifstream desserts{};
    //sets
    void setFileName(std::string);
    //gets
    std::string getFileName();
    //read file and add correct object to vector
    void readFile();
    //recipt display method
    void displayReceipt();
};

Relevant code in Checkout.cpp

   while(desserts >> type >> quantity >> price){
        if(type==1){
            std::cout << "type 1 condition" << '\n';
            std::cout << price << '\n';
            //gets to here and then crashes
            Candy* candy = new Candy(quantity,price);
            dessertList.push_back(candy);
        }

Candy.h

class Candy : public DessertItem{
private:
    double weight;
    double priceLB;
    const std::string itemType= "Candy";
public:
    //construtor
    Candy(double,double);
    //destructor
    ~Candy();
    //sets
    void setWeight(double);
    void setPrice(double);
    //gets
    double getWeight();
    double getPrice();
    //virtual print
    virtual void print();
    //virtual calculate cost
    double calculateCost(double,double);
};

Candy Constructor

Candy :: Candy(double weight, double priceLB):DessertItem(itemType, calculateCost(weight,priceLB)){
    setWeight(weight);
    setPrice(priceLB);
    std::cout << "made candy" << '\n';
}

DessertItem.h

class DessertItem{
private:
    std::string dessertName;
    double dessertCost;
public:
    //construtor
    DessertItem(std::string, double);
    //destructor
    ~DessertItem();
    //sets
    void setName(std::string);
    void setCost(double);
    //gets
    std::string getName();
    double getCost();
    //virtual print
    virtual void print();
    //virtual calculate cost
    virtual double calculateCost();
};

DessertItem.cpp

//constructor accepting 1 argument
DessertItem :: DessertItem(string name, double cost){
    setName(name);
    setCost(cost);
}
//destructor
DessertItem :: ~DessertItem(){}
//sets
void DessertItem :: setName(string name){
    dessertName=name;
}
void DessertItem :: setCost(double cost){
    dessertCost=cost;
}
//gets
string DessertItem:: getName(){
    return dessertName;
}
double DessertItem :: getCost(){
    return dessertCost;
}
//virtual print
void DessertItem :: print(){

}
//virtual calculate cost method
double DessertItem :: calculateCost(){
}

1 Answers1

3

You cannot store polymorphic types by value in a container. What is actually happening when you call push_back is your values are being converted to a DessertItem before being added.

To make use of polymorphism in your container, it must store either a reference or a pointer. You could define your storage as:

std::list<std::unique_ptr<DessertItem>> dessertList;

And then:

dessertList.emplace_back( std::make_unique<Cookie>( quantity, price ) );
dessertList.emplace_back( std::make_unique<Candy>( quantity, price ) );

Your loop is also not great. Don't test for eof. A naive fix for the loop is to convert it as follows:

while( desserts >> type >> quantity >> price )
{
    // ...
}
paddy
  • 60,864
  • 6
  • 61
  • 103
  • I changed this part, but I'm still having trouble even making the object in the first place. I put a cout in the constructor to test it, but it never makes it there. It outputs everything up to the object initialization. – Erik Stryshak Dec 05 '16 at 05:35
  • By "it never makes it", do you mean your program crashes? You should add more code to your question if you want a comment on that. Perhaps you are calling a pure virtual function from the base class constructor. That would be bad. – paddy Dec 05 '16 at 20:57
  • I updated my code above. Even trying to create a candy object does not succeed for some reason within the scope of the loop in the Checkout class. – Erik Stryshak Dec 06 '16 at 05:16
  • You're calling a virtual function on your object before it has even been constructed. You're also using `itemType` before it has been initialized. This is a Bad Idea. – paddy Dec 06 '16 at 05:17
  • Fixing both of those errors corrected the problem. Thank you so much. – Erik Stryshak Dec 06 '16 at 05:31