2017-09-20 14 views
-1

私は、ユーザーがショッピングカートにアイテムを追加して削除できるようにするプログラムを作成しようとしています。この割り当ては、インストラクタによって既に提供されているBagクラスを使用することです。 ShoppingCartクラスはBagクラスから派生します。私は相続財産に苦労して、それを編集しています。クラス継承とテンプレートクラスC++

私は、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 

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; 
} 
+3

可能な重複[テンプレートは、ヘッダーファイルだけで実現することができるのはなぜ?] (https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) –

+0

このトピックでは、実装ファイルを#include tヘッダファイルの終わり。しかし、私がそれをすると、プログラムに存在するすべての関数の再定義エラーが発生します。 – ongelo

+0

IDEがコンパイルしてcppファイルをリンクしていることが原因です。名前をインプットのようなcppではないものに変更して、人々(そしてIDE)がコンパイルされると想定しないようにします。もう一つのやり方は、ヘッダーの場合の分離からほとんど得られないクラス定義から実装を分離しないことです。 – user4581301

答えて

0

あなたの問題は==演算子で、getFrequencyOf()はconstの項目&を比較しようとしていますが、どこにも定義されていないため、失敗していると思います。

はそれで、実際にはいくつかの問題があり、そしてあなたのコードと、割り当てコードの間に明確な境界線なしで、それはあなたが変える必要があることを、確認するのは難しいですが、私の最高の推測

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

bool operator ==(const Item& i1, const Item& i2); 
CONSTバージョンに

した後、実装

// 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()); 

} 
// 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ゲッターを使用しているためコンパイルできないため、それらはすべてconstでなければなりません。その後、あなたはあなたとしてBag.cppを含むことにより、コンパイルして実行することができるはず

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

// 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; 
} 

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

への変更します教授はBag.hとShopの最後に行ったShoppingCart.hの最後のpingCart.cpp

私は複数のファイルプロジェクトを共有する良い方法がわかりませんが、テンプレート実装(Bag.cppとShoppingCart.cpp)を含めて変更することはできません。あなたのファイルは別々にコンパイルされています。なぜなら、main.cppは、const item = &のどこかに==演算子があると仮定しています。 Item.cppには問題はありませんでした。リンカーは必要な機能をすべて見つけることはできないと言った。

UPDATE:初期のコードがなく、ため、テンプレートまたはコンパイルの問題を、正常に実行されなかった

。 < <が同じ問題を抱えていました:オペレータの署名が間違っています。だからgetTotalPriceはコアをダンプしていませんでしたが、cout < < ostream &を返さなかったのでアイテム[0]です。ここでは次のように変更してREPLを働いて更新されます

//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 
+0

コードを1つのファイルにコピーしてコンパイルすると効果的です。次に、 "g ++ -o main main.cpp Item.cpp"と入力して、複数のファイルバージョンをコンパイルすることができました。しかし、getTotalPrice()関数については、 "Segmentation fault(core dumped)"というエラーが発生します。この関数は、1つのファイルでコンパイルすると完全に機能します。なぜか分からない。答えをどうもありがとう、たくさん助けてくれた! – ongelo

+0

あなたの問題は悪い<<演算子、単一/複数のファイルやテンプレートではありませんでした。私の更新された答えを見てください。 –

+0

お世話になりました。 – ongelo

-1

すべてのテンプレート関数をヘッダファイルに実装することを強くお勧めします。クラス定義内ではなく、必要に応じてすべての.hファイルを通常は#includeしないでください。 )。 EDIT:質問を再読します。申し訳ありませんが、私の先生は、テンプレートの場合、常に同じファイルにそれらを実装しました。

+0

ありがとうございました。はい、残念ながら、別々のファイルにする必要がありますが、私はむしろ割り当てを完了させるでしょう。だから私はあなたの提案を試みるでしょう。ありがとうございました。 – ongelo

関連する問題