-1

i've defined the next templated interface which has a cin and cout friend functions:

#ifndef IPRINTABLE_H
#define IPRINTABLE_H

#include <iostream>
using namespace std;

template <class T>
class IPrintable
{
public:
    virtual friend istream &operator>>(istream&, T&) = 0;
    virtual friend ostream &operator<<(ostream&, const T&) = 0;
};

#endif

i tried implanting these functions in a derived class like this:

#ifndef DATE_H
#define DATE_H

#include "IPrintable.h"

class Date : public IPrintable<Date>
{
public:
    Date();
    Date(int, int, int);
    ~Date();

    void setDay(const int);
    void setMonth(const int);
    void setYear(const int);

    friend istream &operator>>(istream&, Date&);
    friend ostream &operator<<(ostream&, const Date&);

private:
    int day;
    int month;
    int year;
};

#endif

but all i got was a bunch of errors: enter image description here i tried searching an answer in the internet, but found nothing helpful, and that's why i'm asking for your help with solving this issue.

i'm new to this concept of inheritance using friend functions in templated interface, so there's a big chance i'm doing something wrong here.

thank you in advance

P.S. how can i solve this problem:

enter image description here

mega5800
  • 87
  • 7

1 Answers1

2

You cannot make a friend function virtual, since it is not a member function. What you want to do is the following:

template <class T>
class IPrintable
{
public:
    virtual void print(std::ostream&) const = 0;
    virtual void read(std::istream&) = 0;
    friend istream &operator>>(istream& in, IPrintable& p) {
        p.read(in);
        return in;
    }
    friend ostream &operator<<(ostream& out, const IPrintable& p) {
        p.print(out);
        return out;
    }
    virtual ~IPrintable() {}
};

class Date : public IPrintable<Date>
{
    // can even be private.
    void print(std::ostream &) const;
    void read(std::istream &);
};

So, what are we doing and why? Having friend functions throughout a class hierachy is complicated (actually I wouldn't know how to do it myself). So we do not even try to make that happen but go around this problem.

We add a friend function to the base class that calls a virtual member function. Since it is a friend, it can call this private function. Since its parameter is a reference, this reference can further bind to all children of the base.

So when a child calls this function (i.e. by std::cout << Date{};), the compiler will call the function taking a reference to the base class and call it. During the call the function print will be called. Since it is virtual and we have overriden it in the child, the override gets called and makes an output specific to the child.

n314159
  • 4,990
  • 1
  • 5
  • 20
  • so should i delete the keyword ```friend``` and try to work it out in the derived class? – mega5800 Jan 03 '20 at 19:56
  • Right idea. Looks like you have written out the need for the template, so I'd remove it. – user4581301 Jan 03 '20 at 19:56
  • @user4581301 i'm writing this program as a part of an assignment i have, where i have to create an IO interface – mega5800 Jan 03 '20 at 19:59
  • @mega5800 , n31459 is demonstrating what's sometimes called the Virtual Friend Function Idiom. You keep the functions, but they don't need to be friends anymore if the virtual function that handles the printing is `public`. – user4581301 Jan 03 '20 at 20:00
  • @mega5800 the need for the template is gone. The stream operators only need to know about the base class. The `virtual` `print` and `read` functions called by the stream operators handle the interface for you. – user4581301 Jan 03 '20 at 20:03
  • n314159, based on the asker's response, I think your answer needs a bit more explanation of what you are doing and why. – user4581301 Jan 03 '20 at 20:04
  • Seems so, I will add it. – n314159 Jan 03 '20 at 20:08
  • @user4581301 i do understand what you mean, but the point is that during this assignment i'll have to create another different class which has to inherit from IPrintable – mega5800 Jan 03 '20 at 20:09