ScholarQuill logoScholarQuillUniversity Notes
  • Notes
  • Past Papers
  • Blogs
  • Todo
Login
ScholarQuill logoScholarQuillUniversity Notes
Login
NotesPast PapersBlogsTodo
More
SubjectsDiscussionCGPA CalculatorGPA CalculatorStudent PortalCourse Outline
About
About usPrivacy PolicyReportContact
Notes
Past Papers
Blogs
Todo
Analytics
    Current Subject
    🧩
    Object Oriented Programming
    COMP2111
    Progress0 / 23 topics
    Topics
    1. Introduction to object oriented design2. History and advantages of object oriented design3. Introduction to object oriented programming concepts4. Classes and objects5. Data encapsulation6. Constructors and destructors7. Access modifiers8. Const vs non-const functions9. Static data members & functions10. Function overloading11. Operator overloading12. Identification of classes and their relationships13. Composition and aggregation14. Inheritance15. Multiple inheritance16. Polymorphism17. Abstract classes and interfaces18. Generic programming concepts19. Function & class templates20. Standard template library21. Object streams22. Data and object serialization using object streams23. Exception handling
    COMP2111›Object streams
    Object Oriented ProgrammingTopic 21 of 23

    Object streams

    8 minread
    1,298words
    Intermediatelevel

    Object Streams in C++

    In C++, object streams are used for input and output operations involving objects. While basic I/O operations typically deal with simple data types (like int, float, and char), object streams are specifically designed to handle more complex types—i.e., instances of user-defined classes.

    The object stream mechanism allows you to serialize (or write) and deserialize (or read) objects to and from files, making it useful for saving and loading object data between different program executions.


    1. Basics of Object Streams

    Object streams rely on two major components:

    • Output Object Streams (std::ofstream for file output, std::ostream for console output)
    • Input Object Streams (std::ifstream for file input, std::istream for console input)

    These object streams are derived from the basic stream classes (std::ostream and std::istream) but are extended to support reading and writing objects instead of basic data types.

    In order to read and write objects, serialization is required—this means converting the object into a byte stream format suitable for storage in a file and later reconstruction.


    2. Serialization and Deserialization

    • Serialization: The process of converting an object’s state (its data) into a format (such as a byte stream) that can be stored or transmitted (e.g., written to a file).
    • Deserialization: The process of reading back the serialized data and reconstructing the object from it.

    To work with object streams in C++, you typically need to overload the << and >> operators for your class so that the data can be read and written correctly.


    3. Overloading << and >> for Object Streams

    To make your class compatible with object streams, you need to overload the insertion operator (<<) for output and the extraction operator (>>) for input.

    • Insertion operator (<<): Used to write (serialize) an object to an output stream (e.g., a file).
    • Extraction operator (>>): Used to read (deserialize) an object from an input stream.

    Here’s how to overload these operators for a class:

    Example: Overloading Operators for Object Streams

    #include <iostream>
    #include <fstream>  // For file streams
    using namespace std;
    
    // Define a class called Person
    class Person {
    private:
        string name;
        int age;
    
    public:
        // Constructor
        Person(string n, int a) : name(n), age(a) {}
    
        // Getter functions
        string getName() const { return name; }
        int getAge() const { return age; }
    
        // Overloading the << operator for serialization (output)
        friend ostream& operator<<(ostream& out, const Person& p) {
            out << p.name << endl;  // Write name to stream
            out << p.age << endl;    // Write age to stream
            return out;
        }
    
        // Overloading the >> operator for deserialization (input)
        friend istream& operator>>(istream& in, Person& p) {
            getline(in, p.name);  // Read name from stream
            in >> p.age;          // Read age from stream
            in.ignore();          // Ignore the newline character after age
            return in;
        }
    };
    
    int main() {
        // Creating a Person object
        Person p1("Alice", 30);
    
        // Writing the object to a file (serialization)
        ofstream outFile("person.dat");  // Open file for writing
        outFile << p1;                   // Use overloaded << to write the object
        outFile.close();
    
        // Reading the object from the file (deserialization)
        Person p2("", 0);  // Creating a temporary Person object
        ifstream inFile("person.dat");  // Open file for reading
        inFile >> p2;  // Use overloaded >> to read the object
        inFile.close();
    
        // Displaying the deserialized data
        cout << "Name: " << p2.getName() << ", Age: " << p2.getAge() << endl;
    
        return 0;
    }
    

    Explanation:

    • In this example, we define a Person class with private members name and age.
    • The insertion operator (<<) writes the name and age of the Person object to an output stream (such as a file).
    • The extraction operator (>>) reads the name and age from an input stream (such as a file) and assigns the values to the corresponding data members of the Person object.

    4. Working with Binary Object Streams

    In addition to text-based object streams (as shown above), you can also use binary streams to store objects in a more efficient binary format. Binary streams can be faster and more compact than text-based streams because they do not require conversion of data into a human-readable format.

    For binary I/O, you use the ofstream and ifstream streams with the ios::binary flag. Here's how you can serialize and deserialize an object to a binary file:

    Example: Binary Object Streams

    #include <iostream>
    #include <fstream>
    using namespace std;
    
    // Define a class called Person
    class Person {
    private:
        string name;
        int age;
    
    public:
        Person(string n = "", int a = 0) : name(n), age(a) {}
    
        // Write the object to a binary file (serialization)
        void writeBinary(ostream& out) const {
            size_t nameLength = name.size();
            out.write(reinterpret_cast<const char*>(&nameLength), sizeof(nameLength));  // Write length of name
            out.write(name.c_str(), nameLength);  // Write the name itself
            out.write(reinterpret_cast<const char*>(&age), sizeof(age));  // Write age
        }
    
        // Read the object from a binary file (deserialization)
        void readBinary(istream& in) {
            size_t nameLength;
            in.read(reinterpret_cast<char*>(&nameLength), sizeof(nameLength));  // Read length of name
            name.resize(nameLength);
            in.read(&name[0], nameLength);  // Read the name
            in.read(reinterpret_cast<char*>(&age), sizeof(age));  // Read age
        }
    
        // Getter functions for name and age
        string getName() const { return name; }
        int getAge() const { return age; }
    };
    
    int main() {
        Person p1("Bob", 25);
    
        // Writing to a binary file
        ofstream outFile("person_binary.dat", ios::binary);
        p1.writeBinary(outFile);
        outFile.close();
    
        // Reading from a binary file
        Person p2;
        ifstream inFile("person_binary.dat", ios::binary);
        p2.readBinary(inFile);
        inFile.close();
    
        // Displaying the deserialized data
        cout << "Name: " << p2.getName() << ", Age: " << p2.getAge() << endl;
    
        return 0;
    }
    

    Explanation:

    • The writeBinary() method writes the object to an output stream in a binary format, first writing the length of the string name and then the name itself, followed by the age.
    • The readBinary() method reads the object from an input stream in binary format.
    • The reinterpret_cast is used to handle the conversion between data types (e.g., converting an integer to a byte representation for storage).

    5. Advantages and Disadvantages of Object Streams

    Advantages:

    • Convenience: Object streams provide a simple way to read and write complex objects directly to files.
    • Persistence: Allows you to save object data to files, which can be loaded back into a program later, enabling persistence between sessions.
    • Flexibility: By overloading the << and >> operators, you can customize how each object is serialized and deserialized.

    Disadvantages:

    • Manual Overloading: You need to manually overload the << and >> operators for each class you want to work with object streams.
    • Binary Format Complexity: Binary serialization requires careful attention to data types and alignment, making it harder to port data between different systems or architectures.

    6. Summary

    • Object Streams allow for reading and writing objects to files, enabling persistence in C++ programs.
    • To use object streams, you typically serialize an object to a stream (write it) and deserialize it from a stream (read it).
    • By overloading the << and >> operators, you control how your class’s data is written and read.
    • Binary object streams can provide more efficient storage than text-based streams, but they require more careful management of data formats.
    Previous topic 20
    Standard template library
    Next topic 22
    Data and object serialization using object streams

    Past Papers

    Open this section to load past papers

    Click on Show Past Papers to see past papers.
    On This Page
      Reading Stats
      Est. reading time8 min
      Word count1,298
      Code examples0
      DifficultyIntermediate