cruella devil
cruella devil

Reputation: 43

How to create IOStream operator overloads so that anything derived from the base class can read from and written to such streams

This is my code so far:


#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <type_traits>


// Abstract base class given - cannot be changed

class basis{
public:
    virtual ~basis() { }  
    virtual std::istream& load(std::istream& is) = 0;  // i.e., pure virtual
    virtual std::ostream& save(std::ostream& os) const = 0;  // i.e., pure virtual
};



// IOStream overloaded functions given - cannot be changed

inline std::ostream& operator<<(std::ostream& os, basis const& b){
    return b.save(os);
}
inline std::istream& operator>>(std::istream& is, basis& b){
    return b.load(is);
}


class vector3d : public basis {
private:
    double x, y, z;


public:
    // Define a public default constructor that initializes the x, y, and z values to 
    // zero values BEFORE execution enters the constructor body

    vector3d() : x{ 0 }, y{ 0 }, z{ 0 } {}      // default constructor 

    // Define a constructor accepting 3 double values (one each for x, y, and z) 
    // and use those arguments to set the constructed object's x, y, and z values 
    // BEFORE execution enters the constructor body
    
    vector3d(double x, double y, double z) : x{ x }, y{ y }, z{ z } {} 



    // Since the parent basis class is abstract, you must
    // Implement the load() and save() functions in your vector3d object. 
    // ******************************************************************
    // Prototypes are given - cannot be changed

    std::istream& load(std::istream& is) override {
        
        /* old version of this function, when vector3d was struct
        char lbraket = '<', comma1 = ',', comma2 = ',', rbraket = '>';
        vector3d temp;

        if ((is >> lbraket >> temp.x >> comma1 >> temp.y >> comma2 >> temp.z >> rbraket)
            && lbraket == '<' && comma1 == ',' && comma2 == ',' && rbraket == '>';){
            v = temp;
            return is;
        }
        else {
            is.setstate(std::ios::failbit);
        }
        */
        return is;
    }
        
    std::ostream& save(std::ostream& os) const override {

        os << '<' << vector3d.x << ',' << vector3d.y << ',' << vector3d.z << '>';
        //os << static_cast <std::underlying_type_t<vector3d>> (x, y, z);
        //os << static_cast <std::underlying_type_t<vector3d>>;

        return os;
    }


    // To perform the summing of vectors, write one more function, 
    // e.g., an operator +() definition. You must write it as a friend 
    // function to the class by first writing in your vector3d class :
    
    friend vector3d operator+(vector3d const& a, vector3d const& b);


};

    
    // Write a definition of this operator +() function(completely outside of your 
    // vector3d class).

vector3d operator+(vector3d const& a, vector3d const& b) {
    vector3d s{ 0,0,0 };

    s.x = a.x + b.x;
    s.y = a.y + b.y;
    s.z = a.z + b.z;

    return s;

    }


// Main given - cannot be changed

int main(){

    unsigned count = 0;
    vector3d sum;
    for (vector3d v; std::cin >> v; ++count)
        sum = sum + v;

    basis& bsum = sum;  // bsum uses sum polymorphically
    std::cout
        << "count: " << count << '\n'
        << "sum: " << bsum << '\n'
        ;
}

I know the load() and save() functions must be defined in vector3d. I know they must be able to input from/output to the console vectors in the format <1.0,2.0,3.0>. Input should be read in as long as the format is correct.

I don't understand how to define the load() and save() functions, or why they are called load and save (if it even matters). I tried everything in the textbook and lecture slides. I can't even find an example of how to write input/output function like these online.

I tried adapting the code from a similar but simpler program where vector3d was a struct instead of a class, but nothing has worked so far.

Upvotes: 0

Views: 34

Answers (1)

cruella devil
cruella devil

Reputation: 43

This worked! Thank you!

std::istream& load(std::istream& is) override {
        char lbraket = '<', comma1 = ',', comma2 = ',', rbraket = '>';
        vector3d temp;

        if ((is >> lbraket >> temp.x >> comma1 >> temp.y >> comma2 >> temp.z >> rbraket)
            && lbraket == '<' && comma1 == ',' && comma2 == ',' && rbraket == '>'){
            *this = temp;
            return is;
        }
        else {
            is.setstate(std::ios::failbit);
        }

        return is;
    }
    
        
    std::ostream& save(std::ostream& os) const override {
        os << '<' << x << ',' << y << ',' << z << '>';
        return os;
    }

Upvotes: 0

Related Questions