在访问私有元素时重载 << 运算符(朋友)

overloading << operator whilst accessing private elements (friend)

我正在编写一个程序,要求我在访问 class 的 private 成员时重载 << 运算符。它是这样的:

A.h

#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;
};

B.h

#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;
}

然而,这并没有打印ab,只是这两个对象的内存地址。我认为这与操作顺序有关,但我不确定。

此外,我不能将 ostream& operator<<() 用作独立函数,因为那样会阻止我访问 class 的私有成员。 我可能会在 class 中实现 void print() 并使用它来打印私有成员,但我认为这不是我教授的想法(考虑到已经实现了 void print()为了别的)。

main()中,ab是指针。此代码:

cout << a
cout << b

实际上是调用这个:

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

因为std::ostream有一个打印指针的成员operator<<(void*),所有指针都可以隐式转换为void*。这就是您在输出中看到内存地址的原因。您的自定义运算符根本没有被调用,因为它们要求您将实际对象实例传递给 operator<<,而您没有这样做。

您需要取消引用 main() 中的指针,例如:

#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;
}

在此代码中:

cout << *a
cout << *b

由于 std::ostream 没有 AB 的成员 operator<<,这将有效地调用它:

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

这将调用您的自定义运算符。

否则,只需完全删除指针即可:

#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;
}

这也将有效地调用这个:

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

从而调用您的自定义运算符。


附带说明一下,您的自定义运算符应该接受对 const A+B 对象的引用,例如:

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