C+中的双边友元函数+;:如何使其编译? 我有以下C++文件:

C+中的双边友元函数+;:如何使其编译? 我有以下C++文件:,c++,friend-function,C++,Friend Function,A.h A.cpp B.cpp #包括“B.h” #包括 #包括“A.h” B::B() { 这->m_b=101; } 空B::B(常数A和A) { std::cout您正在使用未知类型: friend void A::a(const B &b); 编译器只知道类A存在,其他什么都不知道。 您可以将整个类A声明为好友: friend class A; 实际上,在您的例子中,您正在创建一个循环依赖项 通常用前向声明来避免,但据我所知,C++不允许我们对成员函数进行正向声明,所以现在

A.h

A.cpp

B.cpp


#包括“B.h”
#包括
#包括“A.h”
B::B()
{
这->m_b=101;
}
空B::B(常数A和A)
{

std::cout您正在使用未知类型:

friend void A::a(const B &b);
编译器只知道类A存在,其他什么都不知道。 您可以将整个类A声明为好友:

friend class A;

实际上,在您的例子中,您正在创建一个循环依赖项

通常用前向声明来避免,但据我所知,C++不允许我们对成员函数进行正向声明,所以现在看来我不可能。< /P> 但当您将

class
声明为
friend
时,可以打破循环依赖关系

a、 h

a、 cpp

b、 cpp

#包括“b.h”
#包括“a.h”
#包括
B::B()
{
这->m_b=101;
}
空B::B(常数A和A)
{

std::cout不可能有B的成员函数a的朋友和a的成员函数a的朋友

有几种方法可以克服这个问题

  • 以非成员身份编写一个或两个函数。如果需要,请让他们成为这两个类的朋友
  • 使整个类成为另一个类的朋友。如果权限太广,则提取一个较小的类作为朋友
  • 将两个类都转换为类模板(模板参数无关紧要)

    enum单元{u};
    甲级模板;
    B类模板
    {
    静态void foo(){}
    静态空条(){A::foo();}
    friend void A::bar();
    };
    模板类别A
    {
    静态void foo(){}
    静态无效条(){B::foo();}
    friend void B::bar();
    };
    使用AX=A;
    使用BX=B;
    

  • 你试图设置循环依赖。这是一个可怕的事情,它在很多用例中被禁止。在C++中,规则是,在声明后,即使它被完全定义,也可以使用任何对象。问题是,成员只由类的定义声明。所以,如果一个类(B)需要使用的是它定义另一个类的成员(比如A),那么A必须在B.之前定义,因为在同一时间之前不能定义一个定义的B和B,所以在C++中你将无法实现你想要的。
    如果您发现自己试图在B中将a的一个成员设置为friend,在a中将B的一个成员设置为friend,那么您就有了一个一般的设计问题。如果它有意义(从模型的角度来看),可以通过将一个完整的类设置为friend来解决(这是@zmb的答案),或将成员函数更改为非成员。但我强烈建议您返回一步,尝试构建分层模型,而不是循环模型。不幸的是,这成为一个设计问题,而不是编程问题,因此我恐怕无法在以下方面为您提供更多帮助…

    哪一行是错误行?我认为类dB的定义需要在a之前进行,a类的函数也需要在a之后进行定义。您可能需要在标题“a”的顶部添加:class a;class B;以及移动“a”下面的函数可能是重复的,还没有解决,你真的需要朋友函数吗?你不能只在两个类中都有访问函数吗?你不能在C++中实现这个。是的,我知道。但是我们不想把B类暴露给其他可能存在于A中的函数。这和@ ZMB的回答类似。无论如何,谢谢。似乎是最全面的答案,值得接受
    
    #ifndef B_H
    #define B_H
    
    class A;
    
    class B
    {
        private:
            int m_b;
        public:
            B();
            void b(const A &a);
    
        friend void A::a(const B &b); // error: invalid use of incomplete type 'class A'
    };
    
    #endif // B_H
    
    
    #include "B.h"
    #include 
    #include "A.h"
    
    B::B()
    {
        this->m_b = 101;
    }
    
    void B::b(const A &a)
    {
        std::cout << a.m_a << ".\n";
    }
    
    friend void A::a(const B &b);
    
    friend class A;
    
    #ifndef A_H
    #define A_H
    
    #include "b.h"
    
    class B;
    
    class A
    {
        private:
            int m_a;
        public:
            A();
    
            void a(const B &b);
    
        friend class B;
    };
    
    #endif // A_H
    
    #include "a.h"
    #include "b.h"
    #include <iostream>
    
    A::A()
    {
        m_a = 100;
    }
    
    void A::a(const B &b)
    {
        std::cout << b.m_b << ".\n";
    }
    
    #ifndef B_H
    #define B_H
    
    class A;
    
    class B
    {
        private:
            int m_b;
        public:
            B();
            void b(const A &a);
    
        friend class A;
    };
    
    #endif // B_H
    
    #include "b.h"
    #include "a.h"
    #include <iostream>
    
    B::B()
    {
        this->m_b = 101;
    }
    
    void B::b(const A &a)
    {
        std::cout << a.m_a << ".\n";
    }
    
    enum unit {u};
    
    template <unit X> class A;
    
    template <unit X> class B
    {
        static void foo() {}
        static void bar() { A<X>::foo(); }
        friend void A<X>::bar();
    };
    
    template <unit X> class A
    {
        static void foo() {}
        static void bar() { B<X>::foo(); }
        friend void B<X>::bar();
    };
    
    using AX = A<u>;
    using BX = B<u>;