运算符超载与派生类

Operator Overload with Derived Class

本文关键字:派生 超载 运算符      更新时间:2023-10-16

我处于智慧的结尾,几乎没有得到我需要帮助的12个小时之后。我相信我错过了这个问题的基本关键。我有以下代码,对不起,很多,只是不想遗漏任何东西。让我说这确实是HW,但是当您的老师没有回信而Google上没有任何帮助时,我恳求你们所有的智慧和知识。

我的问题:我无法弄清楚如何使linkedbag.h类的操作员 超载。我相信我的原型很好,我只是不知道如何实现它。我尝试了很多事情,例如我写的东西,但是请握住笑声,因为我知道这是错误的,哈。谢谢你的帮助。

main.cpp

** Listing 4-4. */
#include "BagInterface.h"
//#include "ArrayBag.h"
#include "LinkedBag.h"
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
/* no longer used in version 2.1, use << operator 
void displayBag(BagInterface<string>* bagPtr)
{
   cout << "The bag contains " << bagPtr->getCurrentSize()
   << " items:" << endl;
    vector<string> bagItems = bagPtr->toVector();
   int numberOfEntries = (int)bagItems.size();
   for (int i = 0; i < numberOfEntries; i++)
   {
      cout << bagItems[i] << " ";
   }  // end for
   cout << endl;
}  // end displayBag
******/
void bagTester(BagInterface<string>* bagPtr1, BagInterface<string>* bagPtr2)
{
   string items1[] = {"one", "six", "three", "four", "five", "one", "three"};
   string items2[] = {"one", "two", "three", "four", "five", "three"};
   for (int i = 0; i < 7; i++)
   {
      bagPtr1->add(items1[i]);
   }  // end for
   for (int i = 0; i < 6; i++)
   {
      bagPtr2->add(items2[i]);
   }  // end forA
   //displayBag(bagPtr1);
   cout << bagPtr1 << endl;
   cout << boolalpha << "contains 'one' for bag1 returns : " 
    << bagPtr1->contains("one")
           << " frequency: " << bagPtr1-> getFrequencyOf("one")
           <<endl<<endl;
   //displayBag(bagPtr2);
   cout << bagPtr2 << endl;
   cout << boolalpha << "contains 'one' for bag1 returns : " 
    << bagPtr2->contains("one")
           << " frequency: " << bagPtr2-> getFrequencyOf("one")
           <<endl<<endl;
}  // end bagTester
int main()
{
   BagInterface<string>* bagPtr1 = nullptr;
   BagInterface<string>* bagPtr2 = nullptr;
   BagInterface<string>* bagPtr3 = nullptr;
   char userChoice;
   cout << "Enter 'A' to test the array-based implementationn"
   << " or 'L' to test the link-based implementation: ";
   cin >> userChoice;
   if (toupper(userChoice) == 'A')
   {
      //bagPtr1 = new ArrayBag<string>();
      //bagPtr2 = new ArrayBag<string>();
      //bagPtr3 = new ArrayBag<string>();
      //cout << "Testing the Array-Based Bag:" << endl;
   }
   else
   {
      bagPtr1 = new LinkedBag<string>();
      bagPtr2 = new LinkedBag<string>();
      bagPtr3 = new LinkedBag<string>();
      cout << "Testing the Link-Based Bag:" << endl;
   }  // end if
   // test both bags have items
   bagTester(bagPtr1, bagPtr2);
   //test Bag version 2.1 new methods
   //(*bagPtr3) = (*bagPtr1) + (*bagPtr2);
   //cout<<bagPtr3<<endl;
   //bagPtr3->bagSort();
   //cout<<bagPtr3;
   bagPtr1 = nullptr;
   bagPtr2 = nullptr;
   bagPtr3 = nullptr;
   cout << "All done!" << endl;
   return 0;
}  // end main*

baginterface.h

/** Listing 1-1.
    @file BagInterface.h */
#ifndef _BAG_INTERFACE
#define _BAG_INTERFACE
#include <vector>
using namespace std;
template<class ItemType>
class BagInterface
{
public:
    //destructor
    virtual ~BagInterface() {}; 
   /** 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 f ills 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;
    /*******************************************************
    Description     :   Will combine contents of both bags including duplicates into a single bag
    Arguments       :   BagInterface<ItemType>* aBag
    Returns         :   BagInterface<ItemType>*
    Precondition    :   A valid BagInterface pointer object
    Postcondition   :   BagInteface pointer object with combined object elements
    *******************************************************/
   virtual BagInterface<ItemType>* combine( BagInterface<ItemType>* aBag) const = 0;
    /*******************************************************
    Description     :   Will show only items that are different in both bags
    Arguments       :   BagInterface<ItemType>* aBag
    Returns         :   BagInterface<ItemType>*
    Precondition    :   A valid BagInterface pointer object
    Postcondition   :   BagInteface pointer object that points to a bag with only elements
                    :   that are not shared by both bags.
    *******************************************************/
   virtual BagInterface<ItemType>* diff( BagInterface<ItemType>* aBag) const = 0;
    /*******************************************************
    Description     :   Elements that are shared by both bags are returned, no duplicates
    Arguments       :   BagInterface<ItemType>* aBag
    Returns         :   BagInterface<ItemType>*
    Precondition    :   A valid BagInterface pointer object
    Postcondition   :   BagInteface pointer object with elements that are shared with
                    :   both bags, no duplicates
    *******************************************************/
   virtual BagInterface<ItemType>* intersection( BagInterface<ItemType>* aBag) const = 0;
   virtual BagInterface<ItemType>& operator+(const BagInterface<ItemType>& aBag) const = 0;

}; // end BagInterface
#endif

node.h

/** @file Node.h 
    Listing 4-1 */
#ifndef _NODE
#define _NODE
template<class ItemType>
class Node
{
private:
   ItemType        item; // A data item
   Node<ItemType>* next; // Pointer to next node
public:
   Node();
   Node(const ItemType& anItem);
   Node(const ItemType& anItem, Node<ItemType>* nextNodePtr);
   void setItem(const ItemType& anItem);
   void setNext(Node<ItemType>* nextNodePtr);
   ItemType getItem() const ;
   Node<ItemType>* getNext() const ;
}; // end Node
#include "Node.cpp"
#endif

node.cpp

#pragma once
/** @file Node.cpp 
    Listing 4-2 */
#include "Node.h"
#include <cstddef>
template<class ItemType>
Node<ItemType>::Node() : next(nullptr)
{
} // end default constructor
template<class ItemType>
Node<ItemType>::Node(const ItemType& anItem) : item(anItem), next(nullptr)
{
} // end constructor
template<class ItemType>
Node<ItemType>::Node(const ItemType& anItem, Node<ItemType>* nextNodePtr) :
                item(anItem), next(nextNodePtr)
{
} // end constructor
template<class ItemType>
void Node<ItemType>::setItem(const ItemType& anItem)
{
   item = anItem;
} // end setItem
template<class ItemType>
void Node<ItemType>::setNext(Node<ItemType>* nextNodePtr)
{
   next = nextNodePtr;
} // end setNext
template<class ItemType>
ItemType Node<ItemType>::getItem() const
{
   return item;
} // end getItem
template<class ItemType>
Node<ItemType>* Node<ItemType>::getNext() const
{
   return next;
} // end getNext

linkedbag.h

/** ADT bag: Link-based implementation.
    @file LinkedBag.h 
    Listing 4-3 */
#ifndef _LINKED_BAG
#define _LINKED_BAG
#include "BagInterface.h"
#include "Node.h"
template<class ItemType>
class LinkedBag : public BagInterface<ItemType>
{
private:
   Node<ItemType>* headPtr; // Pointer to first node
   int itemCount;           // Current count of bag items
   // Returns either a pointer to the node containing a given entry
   // or the null pointer if the entry is not in the bag.
   Node<ItemType>* getPointerTo(const ItemType& target) const;
public:
   LinkedBag();
   LinkedBag(const LinkedBag<ItemType>& aBag); // Copy constructor
   virtual ~LinkedBag();                       // Destructor should be virtual
   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;
   BagInterface<ItemType>* combine(BagInterface<ItemType>* aBag) const;
   BagInterface<ItemType>* diff(BagInterface<ItemType>* aBag) const;
   BagInterface<ItemType>* intersection(BagInterface<ItemType>* aBag) const;
   BagInterface<ItemType>& operator+(const BagInterface<ItemType>& aBag) const;
}; // end LinkedBag
#include "LinkedBag.cpp"
#endif

linkedbag.cpp

#pragma once
/** ADT bag: Link-based implementation.
    @file LinkedBag.cpp */
#include "LinkedBag.h"
#include "Node.h"
#include <iostream>
using namespace std;
#include <cstddef>
template <class ItemType>
LinkedBag<ItemType>::LinkedBag()
    : headPtr(nullptr)
    , itemCount(0)
{
} // end default constructor
template <class ItemType> LinkedBag<ItemType>::LinkedBag(const LinkedBag<ItemType>& aBag)
{
    itemCount = aBag.itemCount;
    Node<ItemType>* origChainPtr = aBag.headPtr; // Points to nodes in original chain
    if(origChainPtr == nullptr)
    headPtr = nullptr; // Original bag is empty
    else {
    // Copy first node
    headPtr = new Node<ItemType>();
    headPtr->setItem(origChainPtr->getItem());
    // Copy remaining nodes
    Node<ItemType>* newChainPtr = headPtr;  // Points to last node in new chain
    origChainPtr = origChainPtr->getNext(); // Advance original-chain pointer
    while(origChainPtr != nullptr) {
        // Get next item from original chain
        ItemType nextItem = origChainPtr->getItem();
        // Create a new node containing the next item
        Node<ItemType>* newNodePtr = new Node<ItemType>(nextItem);
        // Link new node to end of new chain
        newChainPtr->setNext(newNodePtr);
        // Advance pointer to new last node
        newChainPtr = newChainPtr->getNext();
        // Advance original-chain pointer
        origChainPtr = origChainPtr->getNext();
    } // end while
    newChainPtr->setNext(nullptr); // Flag end of chain
    }                                  // end if
} // end copy constructor
template <class ItemType> LinkedBag<ItemType>::~LinkedBag()
{
    clear();
} // end destructor
template <class ItemType> bool LinkedBag<ItemType>::isEmpty() const
{
    return itemCount == 0;
} // end isEmpty
template <class ItemType> int LinkedBag<ItemType>::getCurrentSize() const
{
    return itemCount;
} // end getCurrentSize
template <class ItemType> bool LinkedBag<ItemType>::add(const ItemType& newEntry)
{
    // Add to beginning of chain: new node references rest of chain;
    // (headPtr is null if chain is empty)
    Node<ItemType>* nextNodePtr = new Node<ItemType>();
    nextNodePtr->setItem(newEntry);
    nextNodePtr->setNext(headPtr); // New node points to chain
    //   Node<ItemType>* nextNodePtr = new Node<ItemType>(newEntry, headPtr); // alternate code
    headPtr = nextNodePtr; // New node is now first node
    itemCount++;
    return true;
} // end add
template <class ItemType> vector<ItemType> LinkedBag<ItemType>::toVector() const
{
    vector<ItemType> bagContents;
    Node<ItemType>* curPtr = headPtr;
    int counter = 0;
    while((curPtr != nullptr) && (counter < itemCount)) {
    bagContents.push_back(curPtr->getItem());
    curPtr = curPtr->getNext();
    counter++;
    } // end while
    return bagContents;
} // end toVector
template <class ItemType> bool LinkedBag<ItemType>::remove(const ItemType& anEntry)
{
    Node<ItemType>* entryNodePtr = getPointerTo(anEntry);
    bool canRemoveItem = !isEmpty() && (entryNodePtr != nullptr);
    if(canRemoveItem) {
    // Copy data from first node to located node
    entryNodePtr->setItem(headPtr->getItem());
    // Delete first node
    Node<ItemType>* nodeToDeletePtr = headPtr;
    headPtr = headPtr->getNext();
    // Return node to the system
    nodeToDeletePtr->setNext(nullptr);
    delete nodeToDeletePtr;
    nodeToDeletePtr = nullptr;
    itemCount--;
    } // end if
    return canRemoveItem;
} // end remove
template <class ItemType> void LinkedBag<ItemType>::clear()
{
    Node<ItemType>* nodeToDeletePtr = headPtr;
    while(headPtr != nullptr) {
    headPtr = headPtr->getNext();
    // Return node to the system
    nodeToDeletePtr->setNext(nullptr);
    delete nodeToDeletePtr;
    nodeToDeletePtr = headPtr;
    } // end while
      // headPtr is nullptr; nodeToDeletePtr is nullptr
    itemCount = 0;
} // end clear
template <class ItemType> int LinkedBag<ItemType>::getFrequencyOf(const ItemType& anEntry) const
{
    int frequency = 0;
    int counter = 0;
    Node<ItemType>* curPtr = headPtr;
    while((curPtr != nullptr) && (counter < itemCount)) {
    if(anEntry == curPtr->getItem()) {
        frequency++;
    } // end if
    counter++;
    curPtr = curPtr->getNext();
    } // end while
    return frequency;
} // end getFrequencyOf
template <class ItemType> bool LinkedBag<ItemType>::contains(const ItemType& anEntry) const
{
    return (getPointerTo(anEntry) != nullptr);
} // end contains
/* ALTERNATE 1
template<class ItemType>
bool LinkedBag<ItemType>::contains(const ItemType& anEntry) const
{
   return getFrequencyOf(anEntry) > 0;
}
*/
/* ALTERNATE 2
template<class ItemType>
bool LinkedBag<ItemType>::contains(const ItemType& anEntry) const
{
   bool found = false;
   Node<ItemType>* curPtr = headPtr;
   int i = 0;
   while (!found && (curPtr != nullptr) && (i < itemCount))
   {
      if (anEntry == curPtr-<getItem())
      {
         found = true;
      }
      else
      {
         i++;
         curPtr = curPtr->getNext();
      }  // end if
   }  // end while
   return found;
}  // end contains
*/
// private
// Returns either a pointer to the node containing a given entry
// or the null pointer if the entry is not in the bag.
template <class ItemType> 
Node<ItemType>* LinkedBag<ItemType>::getPointerTo(const ItemType& anEntry) const
{
    bool found = false;
    Node<ItemType>* curPtr = headPtr;
    while(!found && (curPtr != nullptr)) {
    if(anEntry == curPtr->getItem())
        found = true;
    else
        curPtr = curPtr->getNext();
    } // end while
    return curPtr;
} // end getPointerTo
template <class ItemType> 
BagInterface<ItemType>* LinkedBag<ItemType>::combine(BagInterface<ItemType>* aBag) const
{
    vector<ItemType> items1 = aBag->toVector();
    vector<ItemType> items2 = this->toVector();
    BagInterface<ItemType>* newBag = new LinkedBag<ItemType>();
    if(!aBag->isEmpty()) {
    for(unsigned int i = 0; i < items1.size(); i++) {
        newBag->add(items1[i]);
    }
    }
    if(!this->isEmpty()) {
    for(unsigned int i = 0; i < items2.size(); i++) {
        newBag->add(items2[i]);
    }
    }
    return newBag;
}
template <class ItemType> BagInterface<ItemType>* LinkedBag<ItemType>::diff(BagInterface<ItemType>* aBag) const
{
    vector<ItemType> items1 = this->toVector();
    vector<ItemType> items2 = aBag->toVector();
    BagInterface<ItemType>* newBag = new LinkedBag<ItemType>();
    if(!aBag->isEmpty() && !this->isEmpty()) {
    for(unsigned int i = 0; i < items1.size(); i++) {
        for(unsigned int j = 0; j < items2.size(); j++) {
        if(items1[i] == items2[j]) {
            items1.erase(items1.begin() + i);
            items2.erase(items2.begin() + j);
            i = 0;
            j = -1;
        }
        }
    }
    }
    for(unsigned int i = 0; i < items1.size(); i++) {
    newBag->add(items1[i]);
    }
    return newBag;
}
template <class ItemType> BagInterface<ItemType>* LinkedBag<ItemType>::intersection(BagInterface<ItemType>* aBag) const
{
    vector<ItemType> items1 = this->toVector();
    vector<ItemType> items2 = aBag->toVector();
    BagInterface<ItemType>* newBag = new LinkedBag<ItemType>();
    if(!aBag->isEmpty() && !this->isEmpty()) {
    for(unsigned int i = 0; i < items1.size(); i++) {
        for(unsigned int j = 0; j < items2.size(); j++) {
        if(items1[i] == items2[j]) {
            newBag->add(items1[i]);
            items1.erase(items1.begin() + i);
            items2.erase(items2.begin() + j);
            i = 0;
            j = -1;
        }
        }
    }
    }
    return newBag;
}

template <class ItemType>
BagInterface<ItemType>& LinkedBag<ItemType>::operator+(const BagInterface<ItemType>& aBag) const
{
    //BagInterface<ItemType>* newBag = new LinkedBag();
    //return *newBag;
    BagInterface<ItemType> temp = new LinkedBag(aBag);
        Node<ItemType> *n = headPtr;
        while (n)
        {
            temp.Add(n->data);
            n = n->next;
        }
        n = aBag.headPtr;
        while (n)
        {
            temp.Add(n->data);
            n = n->next;
        }
        return temp;
}

尚不清楚代码中有什么问题,因为不清楚运行它的预期输出是什么。您的代码会产生意外的输出吗?

从快速观察看来,您没有正确声明您的operator+。最有可能而不是返回参考,它应该返回新值。也许您还应该有一种方法可以执行opeartor+采取的类似操作,并使您的operator+简单地调用该方法:

template <class ItemType>
BagInterface<ItemType> LinkedBag<ItemType>::operator+(const BagInterface<ItemType>& aBag) const
{
    return doAdd(aBag); // method that does the same as `operator+`
}

在您的代码中您的operator+返回BagInterface<ItemType>&而不是BagInterface<ItemType>