3

How can make this vector of pointers and then print de Derived1 object and Derived2 object properly ?

Even if I included the "<<" operator in derived classes , it seems that the base class operator is used . And I cannot make the operators virtual because they are not members of the class , they are friend .

What can I do to make the program take the "<<" operator from Derived1 class or Derived2 class and furthermore, print the Base class things, by using :

out << (Base&)temp;

in my operator's definition .

#include<iostream>
#include<fstream>
using namespace std;

class Base {
private:
    int base;
public:
    Base() :base(10){}
    friend ostream& operator<<(ostream& out, const Base& temp)
    {
        out << "======== BASE ========" << endl;
        out << temp.base << endl;
        out << "======== BASE ========" << endl;
        return out;

    }

    friend ofstream& operator<<(ofstream& out, const Base& temp)
    {
        out << "======== BASE ========" << endl;
        out << temp.base << endl;
        out << "======== BASE ========" << endl;
        return out;

    }

};

class Derived1 :public Base {
private :
    int derived1;
public:
    Derived1() :derived1(5){}
        friend ostream& operator<<(ostream& out, const Derived1& temp)
    {
        out << (Base&)temp;
        out << "======== DERIVED1 ========" << endl;
        out << temp.derived1 << endl;
        out << "======== DERIVED1 ========" << endl;
        return out;

    }
    friend ofstream& operator<<(ofstream& out, const Derived1& temp)
    {
        out << (Base&)temp;
        out << "======== DERIVED1 ========" << endl;
        out << temp.derived1 << endl;
        out << "======== DERIVED1 ========" << endl;
        return out;

    }
};

class Derived2 :public Base {
private:
    int derived2;
 public:
    Derived2() :derived2(5) {}
    friend ostream& operator<<(ostream& out, const Derived2& temp)
    {
        out << (Base&)temp;
        out << "======== DERIVED2 ========" << endl;
        out << temp.derived2 << endl;
        out << "======== DERIVED2 ========" << endl;
        return out;
    }
    friend ofstream& operator<<(ofstream& out, const Derived2& temp)
    {
        out << (Base&)temp;
        out << "======== DERIVED2 ========" << endl;
        out << temp.derived2 << endl;
        out << "======== DERIVED2 ========" << endl;
        return out;
    }
};

void main()
{
    Derived1 d1;
    Derived2 d2;
    Base* v[2];
    v[0] = &d1;
    v[1] = &d2;
    cout << *v[0] << endl;
    ofstream f("fis.txt");
    f << *v[0];
}
Victor
  • 31
  • 1
  • 1
    You don't need to add a second output overload for the file stream, an output file stream *is* a output stream. `std::ofstream` inherits from `std::ostream`. – Some programmer dude Jan 31 '16 at 13:50

2 Answers2

2

There are several issues with the shown code

1) It is not necessary to define separate operators for std::ostream and std::ofstream (this was noted in one of the comments)

Since std::ostream is a superclass of std::ofstream, it is only necessary to implement an operator for std::ostream.

2) "using namespace std" is always the wrong thing to do.

3) The main() function should return an int.

Now, to answer the main question here, all that needs to happen here is to employ virtual inheritance. That's what virtual inheritance is for. You know that. Now, just because the operators cannot be virtual, as you noted, there is absolutely no law that prevents them from invoking a virtual method, themselves.

Base's operator<< should just be a facade for some suitably-named function, such as format(), which would be implemented as a virtual method in the class.

The final result would look something like this:

#include<iostream>
#include<fstream>

class Base {
private:
    int base;
public:
    Base() :base(10){}

    friend std::ostream& operator<<(std::ostream& out, const Base& temp)
    {
        temp.format(out);
        return out;
    }

    virtual void format(std::ostream &out) const
    {
        out << "======== BASE ========" << std::endl;
        out << base << std::endl;
        out << "======== BASE ========" << std::endl;
    }

};

class Derived1 :public Base {
private :
    int derived1;
public:
    Derived1() :derived1(5){}

    void format(std::ostream &out) const override
    {
        out << "======== DERIVED1 ========" << std::endl;
        out << derived1 << std::endl;
        out << "======== DERIVED1 ========" << std::endl;

    }
};

class Derived2 :public Base {
private:
    int derived2;
public:
    Derived2() :derived2(5) {}

    void format(std::ostream &out) const override
    {
        out << "======== DERIVED1 ========" << std::endl;
        out << derived2 << std::endl;
        out << "======== DERIVED1 ========" << std::endl;
    }
};

int main()
{
    Derived1 d1;
    Derived2 d2;
    Base* v[2];
    v[0] = &d1;
    v[1] = &d2;
    std::cout << *v[0] << std::endl;
    std::ofstream f("fis.txt");
    f << *v[0];
}
Community
  • 1
  • 1
Sam Varshavchik
  • 84,126
  • 5
  • 57
  • 106
0

Since you cannot make the streaming operator work, as it ain't a member function so cannot be made virtual, you'll have to make another function virtual, and call it from the base's stream operator. You can call it virtual void print()

BitWhistler
  • 1,417
  • 6
  • 12