实现非成员IO运算符

时间:2017-08-14 14:39:17

标签: c++ c++11 input file-io

在我的作业中,我被要求创建Product类,并且我已经完成了除“非成员IO运算符”之外的所有实现。我发现这个问题非常模糊,它要求我重载<<>>运算符以使用ostream和istream来读取产品并将产品打印到控制台以使其成为主要内容功能工作。

在这里,我看到main函数有cout或cin到Product的派生类SItem,我想知道我应该如何实现<< >>运算符来完成主要工作。

我的主要人物:

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include "Product.h"
#include <fstream>
#ifdef TAB
# undef TAB
#endif
#define TAB '\t'
using namespace std;
namespace sict {
    class SItem :public Product {
    public:
        SItem(const char* theSku, const char * theName) :Product(theSku, theName) {}
        SItem() {}
        virtual std::fstream& store(std::fstream& file, bool addNewLine = true)const {
            if (!isEmpty()) {
                file.open("ms4.txt", ios::out | ios::app);
                file << sku() << TAB << name() << TAB << quantity() << TAB << qtyNeeded() << TAB
                    << int(taxed()) << TAB << price() << endl;
                file.clear();
                file.close();
            }
            return file;
        }
        virtual std::fstream& load(std::fstream& file) {
            file.open("ms4.txt", ios::in);
            char buf[2000];
            double dbuf;
            int ibuf;
            file >> buf;
            sku(buf);
            file >> buf;
            name(buf);
            file >> ibuf;
            quantity(ibuf);
            file >> ibuf;
            qtyNeeded(ibuf);
            file >> ibuf;
            taxed(ibuf != 0);
            file >> dbuf;
            price(dbuf);
            file.clear();
            file.close();
            return file;
        }
        virtual std::ostream& write(std::ostream& os, bool linear)const {
            return isEmpty() ? os : (os << sku() << ": " << name() << ", qty: "
                << quantity() << ", qtyNeeded:" << qtyNeeded()
                << ", Cost: " << fixed << setprecision(2) << cost());
        }
        virtual std::istream& read(std::istream& is) {
            char buf[2000];
            double dbuf;
            int ibuf;
            cout << "Sku: ";
            is >> buf;
            sku(buf);
            cout << "Name (no spaces): ";
            is >> buf;
            name(buf);
            cout << "Qty: ";
            is >> ibuf;
            quantity(ibuf);
            cout << "Qty Needed: ";
            is >> ibuf;
            qtyNeeded(ibuf);
            cout << "Is taxed? (1/0): ";
            is >> ibuf;
            taxed(ibuf != 0);
            cout << "Price: ";
            is >> dbuf;
            price(dbuf);
            return is;
        }
    };
}
void dumpFile(fstream& f) {
    f.open("ms4.txt", ios::in);
    char ch;
    while (!f.get(ch).fail()) {
        cout.put(ch);
    }
    f.clear();
    f.close();
}
using namespace sict;
void test() {
    double res, val = 0.0;
    fstream F("ms4.txt", ios::out);
    F.close();
    SItem S;
    SItem T;
    SItem U;
    cout << "Enter Product info: " << endl;
    cin >> S;
    SItem V = S;
    S.store(F);
    T.load(F);
    cout << "T: (store, load)" << endl;
    cout << T << endl;
    cout << "S: " << endl;
    cout << S << endl;
    cout << "V(S): " << endl;
    cout << V << endl;
    cout << "U=T & op= :" << endl;
    U = T;
    cout << U << endl;
    cout << "Operator == :" << endl;
    cout << "op== is " << (T == "1234" ? "OK" : "NOT OK") << endl;
    cout << "op+=: " << endl;
    U += 10;
    cout << U << endl;
    cout << "op+=double : " << endl;
    res = val += U;
    cout << res << "=" << val << endl;
}
int main() {
    fstream F("ms4.txt", ios::out);
    F.close();
    SItem S;
    SItem U("4321", "Rice");
    cout << "Empty Prouduct:" << endl << S << endl;
    cout << "U(\"4321\", \"Rice\"):" << endl << U << endl;

    cout << "Please enter the following information:" << endl;
    cout << "Sku: 1234" << endl;
    cout << "Name(no spaces) : Blanket" << endl;
    cout << "Qty : 12" << endl;
    cout << "Qty Needed : 23" << endl;
    cout << "Is taxed ? (1 / 0) : 1" << endl;
    cout << "Price : 12.34" << endl;
    test();
    cout << "Please enter the following information:" << endl;
    cout << "Sku: 1234" << endl;
    cout << "Name(no spaces) : Jacket" << endl;
    cout << "Qty : 12" << endl;
    cout << "Qty Needed : 23" << endl;
    cout << "Is taxed ? (1 / 0) : 0" << endl;
    cout << "Price : 12.34" << endl;
    test();
    dumpFile(F);
    cout << "----The End" << endl;
    return 0;
}

这是我的Product.h:

namespace sict {
    class Product : public Streamable {
        char sku_[MAX_SKU_LEN + 1];
        char * name_;
        double price_;
        bool taxed_;
        int quantity_;
        int qtyNeeded_;
    public:
        Product();
        Product(const char*, const char*, bool = true, double = 0, int = 0);
        Product(const Product&);
        virtual ~Product();
        Product& operator=(const Product&);
        //setters
        void sku(const char*);
        void price(double);
        void name(const char*);
        void taxed(bool);
        void quantity(int);
        void qtyNeeded(int);
        //getters
        const char* sku()const;
        double price()const;
        const char* name()const ;
        bool taxed()const;
        int quantity()const;
        int qtyNeeded()const;
        double cost()const;
        bool isEmpty()const;
        //member operators
        bool operator==(const char*);
        int operator+=(int);
        int operator-=(int);
    };

    double operator+=(double, const Product&);
    std::ostream& operator<<(std::ostream& ostr, const Product& p);
    std::istream& operator >> (std::istream& istr, Product& p);
}

除最后两个函数外,所有函数都已实现,即IO运算符。

Streamable类是一个没有实现的抽象类。

1 个答案:

答案 0 :(得分:1)

你在很多方面做错了。 在你的情况下最好的方法就是这样做。

首先为您的产品定义流操作的接口:

InputItem

其次定义将使用此接口的流操作符。

class IStreamPrintable
{
public:
     virtual std::ostream& PrintToStream(std::ostream& outStream) const = 0;
};

class IStreamReadable
{
public:
     virtual std::istream& ReadFromStream(std::istream& inputStream) = 0;
};

现在你std::ostream& operator<<(std::ostream& out, const IStreamPrintable& printObject) { return printObject.PrintToStream(out); } std::istream& operator>>(std::istream& input, IStreamReadable& readObject) { return printObject.ReadFromStream(input); } 可以继承这个接口:

Product

您无需立即实施。您可以在特定的产品类class Product : public IStreamPrintable , public IStreamReadable { … }; 中实现这些方法,它将开箱即用。

你的方法SItem完全混乱。您正在传递virtual std::fstream& store(std::fstream& file, bool addNewLine = true)对象并在其上打开一些特定文件。这是错误的,因为您无法将多个对象写入单个文件。保留fstream对象并且不要改变状态(只做写),这样你就可以级联调用,这样就可以避免对文件名进行硬编码。