类继承和模板类C++

Class Inheritance & Template Class C++

本文关键字:C++ 继承      更新时间:2023-10-16

我正在尝试编写一个程序,该程序将允许用户将项目添加到购物车中并删除它们。作业是使用教师已经提供的袋子类。Shoppingcart课程将衍生出袋子课。我正在为继承而苦苦挣扎。

我在bag.h文件末尾的 #include "Bag.cpp"(教授包含)混淆。当我添加#include "ShoppingCart.cpp"等等时,它给了我不同的错误。但是在这种情况下,我会遇到以下错误。如果我添加其中包括,我会得到重新定义错误。

我也将包含哪些文件包含在Putty上的过程中感到困惑。

我知道这是一个很长的问题,但是如果有人为我有一些答案,我会很高兴。在MAIN.CPP中,我没有尝试调用所有功能,基本上我没有完成主要功能。谢谢。

P.S。分配要求我的文件作为标题/实现文件分开。

g++ -o main main.cpp Item.cpp
Undefined                       first referenced
 symbol                             in file
_ZN12ShoppingCartI4ItemEC1Ev        /var/tmp//cc52nA1n.o
_ZN12ShoppingCartI4ItemE3addES0_    /var/tmp//cc52nA1n.o
_Zeq4ItemS_                         /var/tmp//cc52nA1n.o
_ZN12ShoppingCartI4ItemE13getTotalPriceEv /var/tmp//cc52nA1n.o
ld: fatal: symbol referencing errors. No output written to main

baginterface.h

#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

bag.h

#ifndef _BAG
#define _BAG
#include "BagInterface.h"
template<class ItemType>
class Bag : public BagInterface<ItemType>
{
private:
    static const int DEFAULT_BAG_SIZE = 10;
    ItemType items[DEFAULT_BAG_SIZE]; // array of bag items
   int itemCount;                    // current count of bag items 
   int maxItems;                     // max capacity of the bag
   // Returns either the index of the element in the array items that
   // contains the given target or -1, if the array does not contain 
   // the target.
   int getIndexOf(const ItemType& target) const;   
public:
    Bag();
    int getCurrentSize() const;
    bool isEmpty() const;
    bool add(const ItemType& newEntry);
    bool remove(const ItemType& anEntry);
    void clear();
    bool contains(const ItemType& anEntry) const;
    int getFrequencyOf(const ItemType& anEntry) const;
    vector<ItemType> toVector() const; 
};  // end Bag
#include "Bag.cpp"
#endif

bag.cpp

#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

shoppingcart.h

#ifndef SHOPPINGCART_H
#define SHOPPINGCART_H
#include "Bag.h"
#include "Item.h"
#include <iostream>
#include <iomanip>
using namespace std;
template <class ItemType>
class ShoppingCart : public Bag<ItemType> {
private:
    double totalPrice;
public:
    ShoppingCart();
    double getTotalPrice();
    bool add(Item);
    bool remove(Item);
};

#endif //SHOPPINGCART_H

shoppiccart.cpp

#include "ShoppingCart.h"
using namespace std;
// Default Constructor
template <class ItemType>
ShoppingCart<ItemType>::ShoppingCart() {
    totalPrice = 0;
}
template <class ItemType>
bool ShoppingCart<ItemType>::add(Item newItem) {
    bool added = Bag<ItemType>::add(newItem);
    totalPrice = totalPrice + (newItem.getQuantity() * newItem.getPrice());
    return added;
}
template <class ItemType>
bool ShoppingCart<ItemType>::remove(Item anItem) {
    bool removed = Bag<ItemType>::remove(anItem);
    totalPrice = totalPrice - (anItem.getQuantity() * anItem.getPrice());
    return removed;
}
template <class ItemType>
double ShoppingCart<ItemType>::getTotalPrice() {
    return totalPrice;
}

item.h

#ifndef ITEM_H
#define ITEM_H
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
class Item {
private:
    string name;
    double price;
    int quantity;
public:
    Item();
    Item(string n, double p, int q);
    // Setters
    void setName(string s);
    void setPrice(double p);
    void setQuantity(int q);
    // Getters
    string getName();
    double getPrice();
    int getQuantity();
    friend istream& operator >>(istream&, Item&);
};
bool operator ==(Item i1, Item i2);
Item operator <<(ostream& os, Item& source);
#endif //ITEM_H

item.cpp

#include "Item.h"
#include <string>
using namespace std;
Item::Item() {
}
Item::Item(string n, double p, int q) {
    name = n;
    price = p;
    quantity = q;
}
// Setters
void Item::setName(string n) {
    name = n;
}
void Item::setPrice(double p) {
    price = p;
}
void Item::setQuantity(int q) {
    quantity = q;
}
// Getters
string Item::getName() {
    return name;
}
double Item::getPrice() {
    return price;
}
int Item::getQuantity() {
    return quantity;
}
// Definition of the friend function
istream& operator >>(istream& ins, Item& target)
{
    ins >> target.name >> target.price >> target.quantity;
    return ins;
}
// Definition of non-member functions
// << & == operator overloading
bool operator ==(Item& i1, Item& i2) {
    return (i1.getName()==i2.getName() && i1.getPrice()==i2.getPrice()
            && i1.getQuantity()==i2.getQuantity());
}
Item operator <<(ostream& os, Item& source) {
    os << source.getName() << " " << source.getPrice() << " " <<source.getQuantity() << endl;
}

main.cpp

#include "ShoppingCart.h"
#include "Item.h"
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

int main()
{
    cout << "Welcome to XXX SHOPPING CENTER" << endl;
    Item items[10];
    ShoppingCart<Item> cart;
    cout << "Enter the item you selected as the following order:nname unitPrice quantity"
         << "n(Name can not contain any space. Otherwise errors happen!)" << endl;
    cin >> items[0];
    cart.add(items[0]);
    cout << "The shopping cart contains: " << endl;
    cout << items[0];
    cout << "The total price of the order is " << cart.getTotalPrice() << endl;

    return 0;
}

我认为您的问题在== operator中使用,该操作符在getFrequencyOf()中使用,它试图比较const Item&amp;由于在任何地方都没有适当的==定义。

实际上存在几个问题,如果您的代码和作业代码之间没有明确的边界,很难确定,但是我最好的猜测您应该更改

bool operator ==(Item i1, Item i2);

to

bool operator ==(const Item& i1, const Item& i2);

然后,实施

// Definition of non-member functions
// << & == operator overloading
bool operator ==(Item& i1, Item& i2) {
    return (i1.getName()==i2.getName() && i1.getPrice()==i2.getPrice()
            && i1.getQuantity()==i2.getQuantity());
}

const版本

// Definition of non-member functions
// << & == operator overloading
bool operator ==(const Item& i1, const Item& i2) {
    return (i1.getName()==i2.getName() && i1.getPrice()==i2.getPrice()
            && i1.getQuantity()==i2.getQuantity());
}

由于您使用的是非const getters,因此

又不会编译,因此所有这些都应是const。更改

// Getters
string getName();
double getPrice();
int getQuantity();

to

// Getters
const string& getName() const;
//string getName();
double getPrice() const;
int getQuantity() const;

// Getters
string Item::getName() {
    return name;
}
double Item::getPrice() {
    return price;
}
int Item::getQuantity() {
    return quantity;
}

to

// Getters
const string& Item::getName() const {
    return name;
}
double Item::getPrice() const {
    return price;
}
int Item::getQuantity() const {
    return quantity;
}

之后,您应该能够像教授在bag.h和shoppiccart.cpp结束时一样通过包含bag.cpp来进行编译和运行。

我不知道共享多个文件项目的好方法,但是我很确定包括模板实现(bag.cpp and shoppcart.cpp)不会更改它。由于main.cpp假定可能有const item&amp;某处。item.cpp本身没有问题。Linker告诉您,它找不到所需的所有功能。

更新:

初始代码没有成功运行,但不是因为模板或编译的问题。您有Lt;&lt;错误,存在相同的问题:错误的操作员签名。因此,不是getTotalPrice倾倒了核心,而是cout&lt;&lt;项目[0],因为它没有返回Ostream&amp;。这是使用以下更改更新的工作重新录取:

//Item operator <<(ostream& os, Item& source);
std::ostream &operator <<(ostream& os, Item& source);

//Item operator <<(ostream& os, Item& source) {
//    os << source.getName() << " " << source.getPrice() << " " <<source.getQuantity() << endl;
//}
std::ostream &operator <<(ostream& os, Item& source) {
    return os << source.getName() << " " << source.getPrice() << " " <<source.getQuantity() << endl;
}

它输出:

gcc version 4.6.3
Welcome to XXX SHOPPING CENTER
Enter the item you selected as the following order:
name unitPrice quantity
(Name can not contain any space. Otherwise errors happen!)
 ooo 2 3
The shopping cart contains: 
ooo 2 3
The total price of the order is 6

我强烈建议在类定义(不在内部)定义之后(不在内部)中实现所有模板函数,然后根据需要正常使用所有.h文件(换句话说,,不要#cplude您的.cpp文件)。编辑:重新阅读问题。抱歉,我的老师总是让我们在同一文件中实现它们。