I am working on a project for a class. The project is about inheritance. My professor provided us with a base class and gave us instructions to override some of the functions in the base class in the derived class we were asked to create. All of my objects and the client compile separately, but when I try to put it all together I encounter a problem. header, implementation, and client must be separate in this project.
g++ product.o basket.o client.o
client.o:client.cpp:(.text+0x37): undefined reference to`Cart<item>::Cart()'
client.o:client.cpp:(.text+0x147): undefined reference to `Cart<item>::add(item)'
client.o:client.cpp:(.text+0x27b): undefined reference to `Cart<item>::getTotalPrice()'
client.o:client.cpp:(.text+0x3d7): undefined reference to `Cart<item>::add(item)'
client.o:client.cpp:(.text+0x4df): undefined reference to `Cart<item>::remove(item)'
client.o:client.cpp:(.text+0x5fd): undefined reference to `Cart<item>::getTotalPrice()'
client.o:client.cpp:(.text$_ZNK3BagI4itemE10getIndexOfERKS0_[__ZNK3BagI4itemE10getIndexOfERKS0_]+0x4f): undefined reference to `operator==(item const&, item const&)'
client.o:client.cpp:(.text$_ZNK3BagI4itemE14getFrequencyOfERKS0_[__ZNK3BagI4itemE14getFrequencyOfERKS0_]+0x45): undefined reference to `operator==(item const&, item const&)'
collect2.exe: error: ld returned 1 exit status
Here is the code for base class:
#ifndef _BAG_INTERFACE
#define _BAG_INTERFACE
#include <vector>
using namespace std;
template<class ItemType>
class BagInterface
{
public:
/** Gets the current number of entries in this bag.
@return The integer number of entries currently in the bag. */
virtual int getCurrentSize() const = 0;
/** Sees whether this bag is empty.
@return True if the bag is empty, or false if not. */
virtual bool isEmpty() const = 0;
/** Adds a new entry to this bag.
@post If successful, newEntry is stored in the bag and
the count of items in the bag has increased by 1.
@param newEntry The object to be added as a new entry.
@return True if addition was successful, or false if not. */
virtual bool add(const ItemType& newEntry) = 0;
/** Removes one occurrence of a given entry from this bag,
if possible.
@post If successful, anEntry has been removed from the bag
and the count of items in the bag has decreased by 1.
@param anEntry The entry to be removed.
@return True if removal was successful, or false if not. */
virtual bool remove(const ItemType& anEntry) = 0;
/** Removes all entries from this bag.
@post Bag contains no items, and the count of items is 0. */
virtual void clear() = 0;
/** Counts the number of times a given entry appears in bag.
@param anEntry The entry to be counted.
@return The number of times anEntry appears in the bag. */
virtual int getFrequencyOf(const ItemType& anEntry) const = 0;
/** Tests whether this bag contains a given entry.
@param anEntry The entry to locate.
@return True if bag contains anEntry, or false otherwise. */
virtual bool contains(const ItemType& anEntry) const = 0;
/** Empties and then fills a given vector with all entries that
are in this bag.
@return A vector containing all the entries in the bag. */
virtual vector<ItemType> toVector() const = 0;
}; // end BagInterface
#endif
#include "Bag.h"
#include <cstddef>
template<class ItemType>
Bag<ItemType>::Bag() : itemCount(0), maxItems(DEFAULT_BAG_SIZE)
{
} // end default constructor
template<class ItemType>
int Bag<ItemType>::getCurrentSize() const
{
return itemCount;
} // end getCurrentSize
template<class ItemType>
bool Bag<ItemType>::isEmpty() const
{
return itemCount == 0;
} // end isEmpty
template<class ItemType>
bool Bag<ItemType>::add(const ItemType& newEntry)
{
bool hasRoomToAdd = (itemCount < maxItems);
if (hasRoomToAdd)
{
items[itemCount] = newEntry;
itemCount++;
} // end if
return hasRoomToAdd;
} // end add
template<class ItemType>
bool Bag<ItemType>::remove(const ItemType& anEntry)
{
int locatedIndex = getIndexOf(anEntry);
bool canRemoveItem = !isEmpty() && (locatedIndex > -1);
if (canRemoveItem)
{
itemCount--;
items[locatedIndex] = items[itemCount];
} // end if
return canRemoveItem;
} // end remove
template<class ItemType>
void Bag<ItemType>::clear()
{
itemCount = 0;
} // end clear
template<class ItemType>
int Bag<ItemType>::getFrequencyOf(const ItemType& anEntry) const
{
int frequency = 0;
int searchIndex = 0;
while (searchIndex < itemCount)
{
if (items[searchIndex] == anEntry)
{
frequency++;
} // end if
searchIndex++;
} // end while
return frequency;
} // end getFrequencyOf
template<class ItemType>
bool Bag<ItemType>::contains(const ItemType& anEntry) const
{
return getIndexOf(anEntry) > -1;
} // end contains
/* ALTERNATE 1
template<class ItemType>
bool Bag<ItemType>::contains(const ItemType& anEntry) const
{
return getFrequencyOf(anEntry) > 0;
} // end contains
*/
/* ALTERNATE 2
template<class ItemType>
bool Bag<ItemType>::contains(const ItemType& anEntry) const
{
bool found = false;
for (int i = 0; !found && (i < itemCount); i++)
{
if (anEntry == items[i])
{
found = true;
} // end if
} // end for
return found;
} // end contains
*/
template<class ItemType>
vector<ItemType> Bag<ItemType>::toVector() const
{
vector<ItemType> bagContents;
for (int i = 0; i < itemCount; i++)
bagContents.push_back(items[i]);
return bagContents;
} // end toVector
// private
template<class ItemType>
int Bag<ItemType>::getIndexOf(const ItemType& target) const
{
bool found = false;
int result = -1;
int searchIndex = 0;
// if the bag is empty, itemCount is zero, so loop is skipped
while (!found && (searchIndex < itemCount))
{
if (items[searchIndex] == target)
{
found = true;
result = searchIndex;
}
else
{
searchIndex++;
} // end if
} // end while
return result;
} // end getIndexOf
Here is the code for the derived class
#ifndef BASKET_H
#define BASKET_H
#include "Bag.h"
#include "product.h"
#include <iostream>
#include <iomanip>
using namespace std;
template <class ItemType>
class Cart : public Bag<ItemType> {
private:
double totalPrice;
public:
Cart();
double getTotalPrice();
bool add(item);
bool remove(item);
};
#endif
#include "basket.h"
using namespace std;
// Default Constructor
template <class ItemType>
Cart<ItemType>::Cart() {
totalPrice = 0;
}
template <class ItemType>
bool Cart<ItemType>::add(item newItem) {
bool added = Bag<ItemType>::add(newItem);
totalPrice = totalPrice + (newItem.getitemQuantity() * newItem.getitemPrice());
return added;
}
template <class ItemType>
bool Cart<ItemType>::remove(item anItem) {
bool removed = Bag<ItemType>::remove(anItem);
totalPrice = totalPrice - (anItem.getitemQuantity() * anItem.getitemPrice());
return removed;
}
template <class ItemType>
double Cart<ItemType>::getTotalPrice() {
return totalPrice;
}
Here is my main program:
#pragma once
#include <string>
#include "item2.h"
#include "Cart2.h"
#include "Bag.h"
#include "BagInterface.h"
using namespace std;
int main()
{
item itemIn;
Cart<item> shoppingCart;
Bag<item> itemInBag;
int itemCount = 0;
vector<item> showItems;
int modification = 1;
char modify = 'y';
char proceed = 'y';
cout << "hello, thanks for shopping with us" << endl;
cout << "please entr your items as the following: ItemName UnitPrice Quantity" << endl;
cout << "other input formats will casue error!" << endl << "--> " <<endl;
while (proceed == 'y')
{
cin >> itemIn;
shoppingCart.add(itemIn);
cout << "do you wish to add another item? " << endl << "--> ";
cin >> proceed;
if (proceed = 'n')
{break;}
}
itemCount = itemInBag.getCurrentSize();
showItems = itemInBag.toVector();
for (int i = 0; i < itemCount; ++i)
{
cout << showItems[i];
}
cout << "would you like to modify your order? y/n" << endl << "--> " << endl;
cin >> modify;
while (modify = 'y')
{
cout << "do you want to (1) add an item or (2) remove an item? Press the coresponding number." << endl << "-->" << endl;
cin >> modification;
if (modification = 1)
{
}
}
cout << "done";
return 0;
}
Here is the other class we were asked to make:
#ifndef PRODUCT_H
#define PRODUCT_H
#include <iostream>
#include <cstdlib>
#include <string>
#include <iomanip>
using namespace std;
class item
{
private:
string itemName;
double itemPrice;
int itemQuantity;
public:
item();
void setitemName(string);
void setitemPrice(double);
void setitemQuantity(int);
string getitemName() const;
double getitemPrice() const;
int getitemQuantity() const;
friend ostream& operator<<(ostream& os, const item& right);
friend istream& operator>>(istream& is, item& right);
};
bool operator ==(const item& i1, const item& i2);
#endif
#include "product.h"
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <string>
using namespace std;
item::item()
{
}
void item::setitemName(string x)
{
itemName = x;
}
void item::setitemPrice(double y)
{
itemPrice = y;
}
void item::setitemQuantity(int z)
{
itemQuantity = z;
}
string item::getitemName() const
{
return itemName;
}
double item::getitemPrice() const
{
return itemPrice;
}
int item::getitemQuantity() const
{
return itemQuantity;
}
ostream& operator<<(ostream& os, const item& right)
{
os <<right.itemName << right.itemPrice << right.itemQuantity << endl;
return os;
}
istream& operator>>(istream& is, item& right)
{
is >> right.itemName >> right.itemPrice >> right.itemQuantity;
return is;
}
bool operator ==(item& i1, item& i2)
{
return (i1.getitemName()==i2.getitemName() && i1.getitemPrice()==i2.getitemPrice()
&& i1.getitemQuantity()==i2.getitemQuantity());
}
If I am reading the compiler right the problem is probably in the derived class. I am not sure what is going on and would appreciate any help that anyone can give.(Note: My main program isn't finished.)