繁体   English   中英

指定一个class成员function为另一个class的好友?

[英]Specify a class member function as a friend of another class?

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

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

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

我只是想让fB()成为class A朋友,而不是整个class B的朋友。 但是上面的代码产生了一个错误: 'B': is not a class or namespace name (我使用的是 Visual C++ 2005)

尝试将 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(){}
};

A需要B的完整定义。 但是, B需要知道A ,但不需要完整定义,因此您需要A的前向声明。

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

friend void B::fB(A& a);
  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){};
};

还是报错!!!

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

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

4 运行这段代码

////////

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

还是报错!!!

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

  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 练习:

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

为此,需要在A的定义之前知道B的完整定义。

所以向前声明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(){}
};

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

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

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

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

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

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

例如

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

将向我们显示错误,因为 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;
}

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

#include <iostream>
#include <string>
using namespace std;
 
class Manager;
class Employee;
 
class Admin{
    public:
    void EmployeeDetails(Employee &obj);
    void ManagerDetails(Manager &obj);
};
 
class Employee{
    string name = "praful";
    friend void Admin::EmployeeDetails(Employee &obj);    
};
 
class Manager{
    string name = "Robert";
    friend void Admin::ManagerDetails(Manager &obj);
};
 
 
void Admin::EmployeeDetails(Employee &obj)
{
    cout << "Employee :" << obj.name << endl;
}
void Admin::ManagerDetails(Manager &obj)
{
    cout << "Manager :" << obj.name << endl;        
}
 
int main()
{
    Employee e;
    Manager m;
    Admin a;
    a.EmployeeDetails(e);
    a.ManagerDetails(m);
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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