简体   繁体   中英

overloading << operator whilst accessing private elements (friend)

I'm writing a program that requires me to overload the << operator whilst accessing private members of the class. It goes like this:

Ah

#pragma once
#include <ostream>
#include "B.h"

using namespace std;

class A {
public:

    A(B* b) {
        this->b = b;
        this->x = 0;
    }

    friend ostream& operator<<(ostream& os, A& a)
    {
        os << "this is a " << a.x;
        return os;
    }

private:
    int x;
    B* b;
};

Bh

#pragma once
#include <ostream>

using namespace std;

class B {
public:

    B(int x) {
        this->x = x;
    }
    
    friend ostream& operator<<(ostream& os, B& b)
    {
        os << "this is B " << b.x;
        return os; 
    }

private:
    int x;
};

main.cpp

#include <iostream>
#include "A.h"
#include "B.h"

using namespace std;

int main()
{
    B* b = new B(1);
    A* a = new A(b);
    cout << a << endl;
    cout << b << endl;
}

However, this doesn't print a and b , just the memory address of the two objects. I think it has something to do with the order of operations, but I'm not sure on that.

Also, I can't use ostream& operator<<() as an independent function since that would prevent me from accessing the private member of the class. I could potentially implement a void print() inside the class and use that to print the private members, but I don't think that's what my professor has in mind (considering there's already a void print() implemented for something else).

In main() , a and b are pointers. This code:

cout << a
cout << b

Is effectively calling this:

cout.operator<<(a)
cout.operator<<(b)

Because std::ostream has a member operator<<(void*) for printing a pointer, and all pointers are implicitly convertible to void* . This is why you are seeing memory addresses in the output. Your custom operators are not being called at all, as they require you to pass actual object instances to operator<< , which you are not doing.

You need to dereference your pointers in main() , eg:

#include <iostream>
#include "A.h"
#include "B.h"

using namespace std;

int main()
{
    B* b = new B(1);
    A* a = new A(b);
    cout << *a << endl;
    cout << *b << endl;
    delete a;
    delete b;
}

In this code:

cout << *a
cout << *b

Since std::ostream does not have member operator<< s for A or B , this will effectively call this instead:

operator<<(cout, *a)
operator<<(cout, *b)

Which will call your custom operators.

Otherwise, simply get rid of the pointers altogether:

#include <iostream>
#include "A.h"
#include "B.h"

using namespace std;

int main()
{
    B b(1);
    A a(&b);
    cout << a << endl;
    cout << b << endl;
}

Which will also effectively call this:

operator<<(cout, a)
operator<<(cout, b)

Thus calling your custom operators.


On a side note, your custom operators should be accepting references to const A + B objects, eg:

friend ostream& operator<<(ostream& os, const A& a)
friend ostream& operator<<(ostream& os, const B& b)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM