C++ 朋友成员函数行为看起来不稳定

C++ friend member function behaviour looks erratic

我一直试图避免朋友的概念,因为它违背了封装的目的。然而,我只是在试验这个概念,下面的代码无法编译并出现以下错误:

main.cpp:29:28: error: ‘int A::a’ is private within this context

另一方面,如果我只是将 class B 放在 class A 之前,并向前声明 class A,它运行良好。我在这里错过了一些非常微不足道的东西吗?

#include <iostream>

class A {
    int a;

public:
    A() { a = 0; }

    // friend function
    friend void B::showA(A& x);
};

class B
{
    public:
     void showA(A&);
    
    private:
    int b;
    
    
};

void B::showA(A& x)
{
    // Since showA() is a friend, it can access
    // private members of A
    std::cout << "A::a=" << x.a;
}

int main()
{
    A a;
    B b;
    b.showA(a);
    return 0;
}

实际上,您在 class A 中使用了 class B,但是如您所见,B 在使用之前并未声明。 这导致了这样的错误:

error: 'B' has not been declared

还有一点

error: int 'A::a' is private within this context

因为第一个错误导致好友关系没有链接(因为A::a默认是私密的)

你可以试试forward-declare B,像下面这样

#include<..>
class B;
class A {
    int a;

public:
    A() { a = 0; }

    // friend function
    friend void B::showA(A& x);
};
class B{
...
}
...

这会产生一个错误 error: invalid use of incomplete type 'class B' 因为前向声明只说明特定的 class(此处class B)将在稍后定义,因此您可以引用它或指向它,但它没有说明这个class是什么成员 会有,因此编译器无法知道您的 future class B 是否会有 B::showA 方法,因此会出现错误 incomplete type error。这时候编译器不知道你以后的classB(用在classA中)会不会有函数B::showA.

最简单的解决方案是在 A 之前声明 B,然后向前声明 A(使用 class A;),如下所示。这样,你告诉编译器——这是我的 class B 声明(它包含一个方法 B::showA), 它使用我稍后定义的 class A 。由于不需要知道 A 的内容是什么,它会编译。

// as you use class A before it is declared, you need to forward declare it
class A;
class B
{
    public:
     void showA(A&);

    private:
    int b;


};

class A {
    int a;
...

这将编译并执行函数 B::showA