Inheritance/Polymorphism Issue

Since you all have been so helpful recently, I wanted to ask for your help again. I'm getting some invalid output on a program written to demonstrate polymorphism and inheritance with a Grocery store checkout model. I have an abstract Item base class with derived classes of Produce, CannedGood, and Coupon. I have no compilation errors, but when I output my code it's garbage. See below.

*had to cut this up due to length. Rest of program will follow in replies.

1
2
3
4
5
6
7
#ifndef DEFS_H
#define DEFS_H

const int NAME_WIDTH = 15;   // Width of name field on grocery recipt
const int COST_WIDTH = 6;    // width of cost field on grocery recipt

#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef ITEM_H
#define ITEM_H

#include <ostream>
#include <iomanip>
using namespace std;

#include "defs.h"    // Specifies field widths for grocery receipt

class Item 
{
public:
    Item(const char* name = "");          // constructor
    virtual ~Item();                      // destructor
    Item(const Item& other);              // copy constructor
    Item& operator=(const Item& rhs);     // assignment operator

    const char* getName() const;             // return the name of item

    virtual int getCost() const = 0;         // return cost of item in cents
    virtual void print(ostream& out) const = 0; // print the item to out

private:
    char* myName;   // dynamically allocated character array
};

#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "Item.h"

#include<cstring>

//default constructor for Item class
Item::Item( const char* name )
{
    int nameSize = strlen(name);
    char *myName = new char[nameSize + 1];// dynamically allocate space for char array myName based on size of name

}//end default constructor

//class Item destructor
Item::~Item()
{
    delete [] myName;//release pointer-based array space
}//end destructor

//copy constructor for Item class
Item::Item( const Item &other )
{
    int nameSize = strlen( other.myName );
    char *myName = new char[nameSize + 1];// dynamically allocate space for char array myName based on size of name

    for( int i = 0; i < nameSize; i++ )//iterate through both arrays
        myName[ i ] = other.myName[ i ];//copy name's characters into myName array
}//end copy constructor

//overloaded assignment operator
Item &Item::operator =(const Item &rhs)
{
    if( &rhs != this )//don't self-assign
    {
        int myNameSize = strlen( rhs.myName );//get size of rhs
        //if arrays are different sizes, deallocate original
        //and reallocate based on size of rhs
        if( strlen( myName ) != strlen( rhs.myName ) )
        {
            delete [] myName;//deallocate space            
            myName = new char[ myNameSize ];//reallocate space based on new size
        }//end if

        for( int i = 0; i < myNameSize; i++ ) 
            myName[ i ] = rhs.myName[ i ];//copy array into object
    }//end if

    return *this;//enables multiple assignment
}//end overloaded operator=

//function to return name of the Item
const char* Item::getName() const
{
    return myName;//return private variable myName
}//end function name() 




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef PRODUCE_H
#define PRODUCE_H

#include<iostream>

#include "item.h"
using namespace std;

class Produce : public Item
{

public:
    Produce( const char* name, const double &, const int & ); //default constructor
    virtual ~Produce();                  //virtual destructor
    Produce( const Produce& other );  //copy constructor
    Produce& operator=( const Produce& rhs ); //overloaded assignment operator

    double getWeight() const;                  //return weight of the produce
    const char* getName() const;             // return the name of item

    virtual int getCost() const;               //return cost of the item in cents
    virtual void print( ostream& out ) const; //print the item

private: 
    char* myName;  //dynamically allocated character array
    int cost; //integer value of the cost of the canned good
    double weight; //double value of weight of produce in pounds
};
#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include<iostream>
#include "Produce.h" //Produce class definition
using namespace std;

//default constructor for Produce class
Produce::Produce( const char* name, const double &pWeight, const int &cGCost )
:Item( name )
{
    int nameSize = strlen(name);
    myName = new char[ nameSize ];//dynamically allocate space for char array myName based on size of name
    
    cost = cGCost; //store passed cost value in private cost variable
    weight = pWeight; //store passed weight value in private weight variable
}//end default constructor

//class Produce destructor
Produce::~Produce()
{
    delete [] myName;//release pointer-based array space
}//end destructor

//copy constructor for Produce class
Produce::Produce(const Produce &other)
{
    cost = other.getCost(); //assign cost of other variable to this cost
    weight = other.getWeight(); //assign weight of other variable to this weight
    int nameSize = strlen( other.myName );
    char *myName = new char[nameSize + 1];// dynamically allocate space for char array myName based on size of name


    for( int i = 0; i < nameSize; i++ )//iterate through both arrays
    {
        myName[ i ] = other.myName[ i ];//copy name's characters into myName array
    }
}//end copy constructor

//overloaded assignment operator
Produce &Produce::operator =(const Produce &rhs)
{
    if( &rhs != this )//don't self-assign
    {
        int myNameSize = strlen( rhs.myName );//get size of rhs
        //if arrays are different sizes, deallocate original
        //and reallocate based on size of rhs
        if( strlen( myName ) != strlen( rhs.myName ) )
        {
            delete [] myName;//deallocate space            
            myName = new char[ myNameSize ];//reallocate space based on new size
        }//end if

        for( int i = 0; i < myNameSize; i++ ) 
            myName[ i ] = rhs.myName[ i ];//copy array into object
        cost = rhs.getCost();  //assign the cost of rhs to this cost variable
        weight = rhs.getWeight(); //assign the weight of rhs to this weight variable
    }//end if

    return *this;//enables multiple assignment
}//end overloaded operator=

//cost function to return cost of canned good in cents
int Produce::getCost() const
{
    return cost;//return the private variable cost
}//end member-function cost

//weight function to return the weight of produce in pounds
double Produce::getWeight() const
{
    return weight; //return the private variable weight
}//end member-function getWeight

//function to return name of the Item
const char* Produce::getName() const
{
    return myName;//return private variable myName
}//end function name()

//member-function to print the Produce
void Produce::print( ostream &out ) const
{
    cout << setw( NAME_WIDTH + COST_WIDTH ) << getWeight() << " lbs. @ " << getCost() << " /lb." << ""
         << setfill(' ') << setw( NAME_WIDTH ) << getName() << "" 
         << setw ( COST_WIDTH ) << getCost() * getWeight(); //output canned good's name followed by its cost

}//end member-function print 



Thanks for any help you can provide,

airowe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef CANNEDGOOD_H
#define CANNEDGOOD_H

#include<iostream>

#include "item.h"
using namespace std;

class CannedGood : public Item
{

public:
    CannedGood( const char* name, const int & ); //default constructor
    virtual ~CannedGood();                  //virtual destructor
    CannedGood( const CannedGood& other );  //copy constructor
    CannedGood& operator=( const CannedGood& rhs ); //overloaded assignment operator

    const char* getName() const;             // return the name of item

    virtual int getCost() const;               //return cost of the item in cents
    virtual void print( ostream& out ) const; //print the item

private: 
    char* myName;  //dynamically allocated character array
    int cost; //integer value of the cost of the canned good
};
#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<iostream>
#include "CannedGood.h" //CannedGood class definition
using namespace std;

//default constructor for CannedGood class
CannedGood::CannedGood( const char* name, const int &cGCost )
:Item( name )
{
    int nameSize = strlen(name);
    char *myName = new char[nameSize + 1];// dynamically allocate space for char array myName based on size of name

    cost = cGCost; //store passed cost value in private cost variable
}//end default constructor

//class CannedGood destructor
CannedGood::~CannedGood()
{
    delete [] myName;//release pointer-based array space
}//end destructor

//copy constructor for CannedGood class
CannedGood::CannedGood(const CannedGood &other)
{
    cost = other.getCost(); //assign cost of other variable to this cost
    int nameSize = strlen( other.myName );
    myName = new char[ nameSize ];//dynamically allocate space for char array myName based on size of name

    for( int i = 0; i < nameSize; i++ )//iterate through both arrays
    {
        myName[ i ] = other.myName[ i ];//copy name's characters into myName array
    }
}//end copy constructor

//overloaded assignment operator
CannedGood &CannedGood::operator =(const CannedGood &rhs)
{
    if( &rhs != this )//don't self-assign
    {
        int myNameSize = strlen( rhs.myName );//get size of rhs
        //if arrays are different sizes, deallocate original
        //and reallocate based on size of rhs
        if( strlen( myName ) != strlen( rhs.myName ) )
        {
            delete [] myName;//deallocate space            
            myName = new char[ myNameSize ];//reallocate space based on new size
        }//end if

        for( int i = 0; i < myNameSize; i++ ) 
            myName[ i ] = rhs.myName[ i ];//copy array into object
        cost = rhs.getCost();
    }//end if

    return *this;//enables multiple assignment
}//end overloaded operator=

//function to return name of the Item
const char* CannedGood::getName() const
{
    return myName;//return private variable myName
}//end function name()

//cost function to return cost of canned good in cents
int CannedGood::getCost() const
{
    return cost;//return the private variable cost
}//end member-function cost

//member-function to print the CannedGood
void CannedGood::print( ostream &out ) const
{
    cout << setw( NAME_WIDTH ) << getName() << ""
         << setfill(' ') << setw( COST_WIDTH ) << getCost()/100; //output canned good's name followed by its cost
     
}//end member-function print 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef COUPON_H
#define COUPON_H

#include<iostream>

#include "item.h"
using namespace std;

class Coupon : public Item
{

public:
    Coupon( const char* name, const int & ); //default constructor
    virtual ~Coupon();                  //virtual destructor
    Coupon( const Coupon& other );  //copy constructor
    Coupon& operator=( const Coupon& rhs ); //overloaded assignment operator

    const char* getName() const;             // return the name of item

    virtual int getCost() const;               //return cost of the item in cents
    virtual void print( ostream& out ) const; //print the item

private: 
    char* myName;  //dynamically allocated character array
    int cost; //integer value of the cost of the canned good
};
#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include<iostream>
#include "Coupon.h" //Coupon class definition
using namespace std;

//default constructor for Coupon class
Coupon::Coupon( const char* name, const int &cGCost )
:Item( name )
{
    int nameSize = strlen(name);
    char *myName = new char[nameSize + 1];// dynamically allocate space for char array myName based on size of name

    
    cost = ( cGCost > 0 ? cGCost: 0 ); //store passed cost value in private cost variable
}//end default constructor

//class Coupon destructor
Coupon::~Coupon()
{
    delete [] myName;//release pointer-based array space
}//end destructor

//copy constructor for Coupon class
Coupon::Coupon(const Coupon &other)
{
    cost = other.getCost(); //assign cost of other variable to this cost
    int nameSize = strlen( other.myName );
    myName = new char[ nameSize ];//dynamically allocate space for char array myName based on size of name

    for( int i = 0; i < nameSize; i++ )//iterate through both arrays
    {
        myName[ i ] = other.myName[ i ];//copy name's characters into myName array
    }
}//end copy constructor

//overloaded assignment operator
Coupon &Coupon::operator =(const Coupon &rhs)
{
    if( &rhs != this )//don't self-assign
    {
        int myNameSize = strlen( rhs.myName );//get size of rhs
        //if arrays are different sizes, deallocate original
        //and reallocate based on size of rhs
        if( strlen( myName ) != strlen( rhs.myName ) )
        {
            delete [] myName;//deallocate space            
            myName = new char[ myNameSize ];//reallocate space based on new size
        }//end if

        for( int i = 0; i < myNameSize; i++ ) 
            myName[ i ] = rhs.myName[ i ];//copy array into object
        cost = rhs.getCost();
    }//end if

    return *this;//enables multiple assignment
}//end overloaded operator=

//function to return name of the Item
const char* Coupon::getName() const
{
    return myName;//return private variable myName
}//end function name()

//cost function to return cost of coupon in cents
int Coupon::getCost() const
{
    return cost;//return the private variable cost
}//end member-function cost

//member-function to print the Coupon
void Coupon::print( ostream &out ) const
{
    cout << setw( NAME_WIDTH ) << getName() << ""
         << setfill(' ') << setw( COST_WIDTH ) << getCost()/100; //output coupon's name followed by its cost

}//end member-function print 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <iomanip>
using namespace std;

#include "defs.h"    // Specifies field widths for grocery receipt

#include "Item.h"
#include "CannedGood.h"
#include "Produce.h"
#include "Coupon.h"

int main()
{
    Item* items[100];   // Array of pointers to Items to checkout
    int numItems = 0;   // Number of Items added to the items array
    int totalCost = 0;  // Total cost of all the Items to checkout

    // Add Items to be checked out
    items[numItems++] = new Produce("Bananas", 5.3, 49);
    items[numItems++] = new CannedGood("Vegetable Soup",89);
    items[numItems++] = new Produce("Apples", 3.299, 109);
    items[numItems++] = new CannedGood("Green Beans",59);
    items[numItems++] = new CannedGood("Corn",49);
    items[numItems++] = new CannedGood("Baked Beans",79);
    items[numItems++] = new Produce("Watermelon", 11.303, 89);
    items[numItems++] = new CannedGood("Fruit Cocktail",45);
    items[numItems++] = new CannedGood("Tomato Soup",49);
    items[numItems++] = new Coupon("Vegetable Soup",10);
    items[numItems++] = new Coupon("Corn",15);

    // Output the grocery receipt header
    cout << "CSC234 Grocery Store" << endl
         << setfill('-') << setw(NAME_WIDTH + COST_WIDTH) << ""
         << setfill(' ')
         << endl << endl;

    // Print the Items on the grocery receipt
    for (int i = 0; i < numItems; ++i)
    {
        items[i]->print(cout);
        cout << endl << endl;

        // Add cost of current Item to total cost
        totalCost += items[i]->getCost();
    }

    // Print out the total cost
    cout << left << setw(NAME_WIDTH) << "Total Cost"
         << right << fixed << setprecision(2)
         << setw(COST_WIDTH) << totalCost/100.0
         << endl;
}




Last edited on
Topic archived. No new replies allowed.