简体   繁体   English

实施非成员IO操作员

[英]Implementing a non-member IO operator

In my assignment I was asked to create the Product class, and I have finished all the implementations except the "non-member IO operator". 在我的作业中,我被要求创建Product类,并且完成了除“非成员IO操作员”之外的所有实现。 The question I found it very vague, it asks me to overload the << and >> operators to work with ostream and istream to read a Product from and print a Product to the console in order to make this main function work. 我发现这个问题很模糊,它要求我重载<<>>运算符以与ostream和istream一起使用以从控制台读取产品并将产品打印到控制台,以使此主要功能正常工作。

Here I see the main function has cout or cin to Product's derived class SItem, I wonder how I should implement the << >> operators to make the main work. 在这里,我看到main函数对Product的派生类SItem具有cout或cin,我想知道如何实现<< >>运算符以使主要功能起作用。

My main: 我的主要:

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

This is my Product.h: 这是我的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);
}

All the functions have been implemented except the last two, which are the IO operators. 除了最后两个输入输出操作员,所有功能都已实现。

Streamable class is an abstract class that has no implementations. Streamable类是没有实现的抽象类。

You did this wrong in many ways. 您以多种方式犯了这个错误。 Best approach in your case is do it like that. 在您的情况下,最好的方法就是这样做。

First define interfaces for stream operations, for your products: 首先为您的产品定义用于流操作的接口:

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

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

Secondly define stream operators which will use this interfaces. 其次,定义将使用此接口的流运算符。

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

Now you Product can inherit this interfaces: 现在,您的Product可以继承以下接口:

class Product 
    : public IStreamPrintable
    , public IStreamReadable
{
   …
};

You do not have to implement it immediately. 您不必立即实施它。 You can implement those methods in specific product classes SItem and it will work out of the box. 您可以在特定的产品类SItem实现这些方法, SItem

Your method virtual std::fstream& store(std::fstream& file, bool addNewLine = true) is total mess. 您的方法virtual std::fstream& store(std::fstream& file, bool addNewLine = true)是一团糟。 You are passing fstream object and opening some specific file on it. 您正在传递fstream对象并在其上打开一些特定文件。 This is wrong since you are unable to write multiple objects to single file. 这是错误的,因为您无法将多个对象写入单个文件。 Keep there ostream object and do not change is state (do only writing), so you could cascade calls and so you could avoid hard-coding a file name. ostream对象保留在那里,并且不要更改状态(仅写操作),这样您可以级联调用,从而避免硬编码文件名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM