Search code examples
c++objectoopoperators

friend operator << and >> in base class without child class but still called


Why is the operators << and >> called in base class if they are defined as 'friend' when calling << and >> in child class?

Code:

#include <iostream>
#include <memory>
#include <vector>

using namespace std;

class Baza
{
protected:
    int n;
public:
    Baza() { cout << "B\n"; }
    virtual ~Baza() { cout << "~B\n"; }

    friend istream& operator>>(istream& in, Baza& b);
    friend ostream& operator<<(ostream& out, const Baza& b);
};

istream& operator>>(istream& in, Baza& b)
{
    cout<<"op >>"<<endl;
    return in;
}

ostream& operator<<(ostream& out, const Baza& b)
{
    cout<<"op<<"<<endl;
    return out;
}

class Derivata : public Baza
{
public:
    Derivata() { cout << "D\n"; }
    ~Derivata() { cout << "~D\n"; }


};



int main()
{
    vector<Derivata> v;
    v.push_back(new Derivata);

// works
    Derivata d;
    cin>>d;
    cout<<d;

    return 0;
}

Is c++ compiler creating a operators that calls the base class method's operator by default when compiling?

Rephrase: in base class (which is baza) are defined operators << and >> as friend. Derivata class inherits the 'baza' (base class), but operators are not inherited because they're friends. why are they called if i use >> and << in 'derivata' class?


Solution

  • The operator>> and operator<< you've defined are in no way part of the Baza class. The friend keyword doesn't do that; it just gives them permission to access Baza's private and protected members.

    In that way, what you have is no different from this:

    class Baza {};
    class Derivata : public Baza {};
    
    void some_function(Baza&) {}
    
    int main() {
        Derivata d;
        some_function(d);
    }
    

    A reference to a base class can be bound to an object of a class derived from that base class, so a Baza& can be bound to a Derivata object. That allows you to pass objects of the derived class to functions that accept references to the base class.

    Replacing some_function with an overloaded operator doesn't change anything about the semantics of how it's looked up or what objects can be passed to it. All it changes is the syntax used to call it.