C++ 将类成员函数指定为另一个类的友元?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10546391/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:12:12  来源:igfitidea点击:

Specify a class member function as a friend of another class?

c++friend

提问by ipkiss

According to the C++ Primer book, the author mentioned that We can specify a class member function as a friend of another class, instead of the entire class (page 634).

根据 C++ Primer 一书,作者提到我们可以将类成员函数指定为另一个类的友元,而不是整个类(第 634 页)。

Then, I tested this code:

然后,我测试了这段代码:

class A
{
public:
    friend void B::fB(A& a);
    void fA(){}
};
class B
{
public:
    void fB(A& a){};
    void fB2(A& a){};
};

I just wanted the fB() to be friend of class A, not the entire class B. But the about code produced an error: 'B' : is not a class or namespace name. (I am using Visual C++ 2005)

我只是想FB()是A级的朋友,而不是整个类B.但有关代码产生的错误:'B' : is not a class or namespace name。(我使用的是 Visual C++ 2005)

回答by juanchopanza

Try putting the B definition before A's:

尝试将 B 定义放在 A 之前:

class A; // forward declaration of A needed by B

class B
{
public:
    // if these require full definition of A, then put body in implementation file
    void fB(A& a); // Note: no body, unlike original.
    void fB2(A& a); // no body.
};

class A
{
public:
    friend void B::fB(A& a);
    void fA(){}
};

Aneeds the full definition of B. However, Bneeds to know about A, but does not need the full definition, so you need the forward declaration of A.

A需要完整的定义B。但是,B需要知道 about A,但不需要完整定义,因此需要A.

回答by SrinivasPaladugu

When the compiler starts compiling the code( usually from top ) and it encounters this line:

当编译器开始编译代码(通常从 top 开始)并遇到以下行时:

friend void B::fB(A& a);
  1. at this point, compiler has no idea about type info of B so it throws an error ( 'B' : is not a class or namespace name ).
  2. by forward declaration of class B, compiler knows about type of B is Class in advance to its actual declaration with all members.

  3. run below code after forward declaration of class B.

  1. 此时,编译器不知道 B 的类型信息,因此它会引发错误( 'B' : is not a class or namespace name )。
  2. 通过类 B 的前向声明,编译器在其所有成员的实际声明之前就知道 B 的类型是 Class。

  3. 在 B 类前向声明​​后运行下面的代码。

///////////////

///////////////

class B;
class A
{
public:
    friend void B::fB(A& a); 
    void fA(){};
};
class B
{
public:
    void fB(A& a){};
    void fB2(A& a){};
};

Still error !!!

还是报错!!!

because forward declaration is just a declaration of an identifier for which the programmer has not yet given a complete definition. so compiler needs full definition of B before class A.

因为前向声明只是一个标识符的声明,程序员还没有给出完整的定义。所以编译器需要在类 A 之前完整定义 B。

Note: class A definition dependents on type of B and also definition of B (i.e B::fB) so that forward declaration alone can not resolve, complete definition of class B needs to define before class A.

注意:A 类定义依赖于 B 的类型以及 B 的定义(即 B::fB),因此仅靠前向声明无法解析,B 类的完整定义需要在 A 类之前定义。

4 run this code

4 运行这段代码

////////

////////

class B
{
public:
    void fB(A& a){};
    void fB2(A& a){};
};
class A
{
public:
    friend void B::fB(A& a); 
    void fA(){}
};

Still error !!!

还是报错!!!

because class B member functions fB & fB2 having arguments of type A but compiler has no idea about type info of A so by forward declaration of class A, we can let compiler knows about type info of A. Note: class B definition only dependent on type of A not the members of A so that forward declaration of A resolve step 4.

因为 B 类成员函数 fB & fB2 具有类型 A 的参数,但编译器不知道 A 的类型信息,所以通过类 A 的前向声明,我们可以让编译器知道 A 的类型信息。 注意:B 类定义仅依赖于A 的类型不是 A 的成员,以便 A 的前向声明解决步骤 4。

  1. final code
  1. 最终代码

////////////////////////

////////////////////////

class A;  // forward declaration of A needed by B
class B
{
public:
    void fB(A& a);
};

class A
{
    int i;
public:
    friend void fA(A& a);    //specifying function fA as a friend of A, fA is not member function of A
    friend void B::fB(A& a); //specifying B class member function fB as a friend of A
};

// fA is Friend function of A
void fA(A& a)
{
    a.i  = 11; // accessing and modifying Class A private member i
    cout<<a.i<<endl;
}

// B::fB should be defined after class A definition only because this member function can access Class A members
void B::fB(A& a)
{
    a.i  = 22; // accessing and modifying Class A private member i in Class B member function fB
    cout<<a.i<<endl;
}

int main()
{
    A a;
    fA(a);    // calling friend function of class A

    B b;
    b.fB(a);  // calling B class member function fB, B:fB is friend of class A

    return 0;
}

6 Exercise:

6 练习:

// Cyclic dependency 
#include<iostream>
using namespace std;

class A;

class B
{
public:
    void fB(A& a);
    friend void A::fA(B& b); //specifying class A's member function fA as a friend of B
};

class A
{
    int i;
public:
    void fA(B& b);  
    friend void B::fB(A& a); //specifying class B's member function fB as a friend of A
};

int main()
{
    return 0;
}

回答by Luchian Grigore

For this to work, the full definition of Bneeds to be known before the definition of A.

为此,B需要在定义之前了解 的完整定义A

So forward declare A, since Bdoesn't need the full type, and switch the definitions around:

所以 forward declare A,因为B不需要完整类型,并切换定义:

class A;
class B
{
public:
    void fB(A& a){};
    void fB2(A& a){};
};
class A
{
public:
    friend void B::fB(A& a);
    void fA(){}
};

回答by AbhimanyuAryan

When the compiler starts reading the code( usually from top ) and it encounters this line:

当编译器开始读取代码(通常从 top )并遇到以下行时:

friend void B::fB(A& a);

friend void B::fB(A& a);

Then compiler doesn't understand what do you mean by this B::. Even if you have defined this class later in the code but compiler doesn't know that. So it's usually a good to practice to do forward declaration of class( class Name;) if the definition resides later in the code.

然后编译器不明白你的意思是什么B::。即使您稍后在代码中定义了这个类,但编译器不知道。因此,class Name;如果定义位于代码的后面,那么练习对 class( )进行前向声明通常是一个很好的做法。

回答by abdul rizwan

firstly forward declare class A, so that its visible in class B definition. then define class A containing a friend function from class B.

首先转发声明A类,使其在B类定义中可见。然后定义包含来自类 B 的友元函数的类 A。

回答by New_Bee

First of all before using a particular class name you will have to declare it first. So you will need a forward declaration of the Class B as you are using it in Class A before the Class B has been originally declared.

首先,在使用特定的类名之前,您必须先声明它。因此,在最初声明 B 类之前,在 A 类中使用它时,您将需要 B 类的前向声明。

Secondly you will need to define the functions (that are using variables from both the classes- here the friend functions ) after both the classes have been defined. Or else we may face errors.

其次,在定义了两个类之后,您需要定义函数(使用来自两个类的变量——这里是友元函数)。否则我们可能会遇到错误。

For example

例如

#include<iostream>

using namespace std;

class alpha1;

class alpha2
{
    public:

        void put_bata(int a,int b);
};

void alpha2 :: put_bata(int a,int b)
{
    alpha1 net;

    net.roll=a;

    net.id=b;

    net.get_data();
}

class alpha1
{
    int roll;

    int id;

    public:

        void get_data(void)
        {
            cout<<roll<<endl<<id<<endl;
        }

        friend void alpha2 :: put_bata(int a,int b);
};

int main()
{
    alpha2 gamma;

    gamma.put_bata(5,6);

    return 0;
}

Will show us errors as put_bata tries to access roll and id before they are defined even if we had a forward declaration of the class but the code given below will just work fine.

将向我们显示错误,因为 put_bata 尝试在定义之前访问 roll 和 id,即使我们有类的前向声明,但下面给出的代码将正常工作。

#include<iostream>

using namespace std;

class alpha1;

class alpha2
{
    public:

        void put_bata(int a,int b);
};

class alpha1
{
    int roll;

    int id;

    public:

        void get_data(void)
        {
            cout<<roll<<endl<<id<<endl;
        }

        friend void alpha2 :: put_bata(int a,int b);
};

void alpha2 :: put_bata(int a,int b)
{
    alpha1 net;

    net.roll=a;

    net.id=b;

    net.get_data();
}


int main()
{
    alpha2 gamma;

    gamma.put_bata(5,6);

    return 0;
}

回答by mrboieng

@juanchopanza @ipkiss Regarding the problem that you can't access data members of A inside fB(A& a) because A is not defined yet. Instead of defining it in a separate file and including it, you can just define the function fB(A& a) after the definition of class A so that fB(A& a) is able to see data members of A.

@juanchopanza @ipkiss 关于由于 A 尚未定义而无法访问 fB(A& a) 内的 A 数据成员的问题。无需在单独的文件中定义并包含它,您只需在类 A 的定义之后定义函数 fB(A& a),以便 fB(A& a) 能够看到 A 的数据成员。