J'essaye d'écrire un programme qui permettra à l'utilisateur d'ajouter des articles dans un panier et de les supprimer. L'affectation consiste à utiliser la classe Bag qui est déjà fournie par l'instructeur. La classe ShoppingCart dérivera de la classe Bag. Je me bats avec l'héritage et je le compile.Classe Héritage & Modèle Classe C++
Je suis confondu avec le #include "Bag.cpp"
à la fin du fichier Bag.h (qui est inclus par le professeur). Lorsque j'ajoute #include "ShoppingCart.cpp"
et autres, cela me donne des erreurs différentes. Mais dans ce cas, j'obtiens l'erreur suivante. Si j'ajoute ces includes, j'obtiens des erreurs de redéfinition.
Je suis également confus avec les fichiers à inclure pour le processus de compilation sur PuTTy.
Je sais que c'est une très longue question, mais je serai heureux si quelqu'un a des réponses pour moi. Dans le main.cpp je n'ai pas essayé d'invoquer toutes les fonctions, fondamentalement je n'en ai pas fini avec le principal. Je vous remercie.
P.S. L'affectation nécessite que mes fichiers soient séparés en tant que fichiers d'en-tête/d'implémentation.
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
ShoppingCart.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;
}
double possible de [Pourquoi les modèles ne seront mis en œuvre dans le fichier d'en-tête?] (https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) –
Dans cette rubrique, il est suggéré d'utiliser #include le fichier d'implémentation t la fin du fichier d'en-tête. Cependant, quand je fais cela, je reçois des erreurs de redéfinition pour chaque fonction qui existe dans le programme. – ongelo
Les chances sont parce que votre IDE voit compiler et lie le fichier cpp. Changez le nom en quelque chose qui n'est pas cpp comme impl pour que les gens (et l'IDE) ne supposent pas qu'il doit être compilé.Une autre astuce consiste à ne pas séparer les implémentations des définitions de classe que vous ne gagnez pas beaucoup de la séparation dans le cas d'un en-tête. – user4581301