本文主要介绍一下C++中的友元函数和友元类的使用。

1. 友元函数

其实友元函数又可以分为:

  • 普通友元函数

  • 友成员函数

1.1 普通友元函数

代码中有一个全局函数,该函数想要去访问某个类的成员变量(该类的成员变量是private的,且该类并未提供任何获取其私有成员变量的public方法),这时候可以在这个类中把该全局函数声明为友元函数,这样这个全局函数就具备了能够获取那个类的私有成员变量的资格。

注:

1)普通友元函数不是类成员函数,而是一个类外的函数,但是可以访问类所有成员。

2) 可以将普通友元函数声明在类的任何一个section(public/protected/private)

参看如下示例,通过友元函数获取Person对象的各字段信息(test.cpp):

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>


class Person{
public:
        Person(char *name, int age, int sex);
        ~Person(){}

private:
        std::string name;
        int age;
        int sex;

private:
        friend void showPersonInfo(Person *p);

};

Person::Person(char *name, int age, int sex)
  :name(name),
   age(age),
   sex(sex){
}

void showPersonInfo(Person *p)
{
        std::cout<<"name: "<<p->name<<" age: "<<p->age<<" sex: "<<(p->sex==0?"male":"female")<<std::endl;
}

int main(int argc, char *argv[])
{
        Person p((char *)"ivan1001", 20, 0);

        showPersonInfo(&p);

        return 0x0;
}

编译运行:

# gcc -o test test.cpp -lstdc++
# ./test
name: ivan1001 age: 20 sex: male

1.2 友成员函数

假设有两个类,分别为class Aclass B。class A的一个成员函数想访问class B的私有成员变量,此时我们可以在class B中将class A的成员函数声明为友元函数。

参看如下示例,打印Person类的详细信息(包含姓名,年龄,性别,省份,城市,街道):

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>


class Address;

class Person{
public:
        Person(char *name, int age, int sex);
        ~Person(){}

private:
        std::string name;
        int age;
        int sex;

public:
        void showAddressInfo(Address *paddr);

};



class Address{
public:
        Address(char *province, char *city, char *district);

        ~Address(){}

private:
        std::string province;
        std::string city;
        std::string district;

private:
        friend void Person::showAddressInfo(Address *paddr);
};


Person::Person(char *name, int age, int sex)
  :name(name),
   age(age),
   sex(sex){
}

Address::Address(char *province, char *city, char *district)
  :province(std::string(province)),
   city(city),
   district(district){

}

void Person::showAddressInfo(Address *paddr)
{
        std::cout<<"province: "<<paddr->province<<" city: "<<paddr->city<<" district: "<<paddr->district<<std::endl;
}


int main(int argc, char *argv[])
{
        Person p((char *)"ivan1001", 20, 0);
        Address addr((char *)"Guangdong", (char *)"Shenzhen", (char *)"Nanshan");

        p.showAddressInfo(&addr);

        return 0x0;
}

编译运行:

# gcc -o test test.cpp -lstdc++
# ./test
province: Guangdong city: Shenzhen district: Nanshan

2. 友元类

友元类则更为简单,可以将class A声明为class B的友元类,那么class A就拥有了能够访问class B所有成员的资格,包括private、protected、public的。

参看如下示例:

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>


class Address;

class Person{
public:
        Person(char *name, int age, int sex);
        ~Person(){}

private:
        std::string name;
        int age;
        int sex;

public:
        void showAddressInfo(Address *paddr);

};



class Address{
public:
        Address(char *province, char *city, char *district);

        ~Address(){}

private:
        std::string province;
        std::string city;
        std::string district;

private:
        friend class Person;
};


Person::Person(char *name, int age, int sex)
  :name(name),
   age(age),
   sex(sex){
}

Address::Address(char *province, char *city, char *district)
  :province(std::string(province)),
   city(city),
   district(district){

}

void Person::showAddressInfo(Address *paddr)
{
        std::cout<<"province: "<<paddr->province<<" city: "<<paddr->city<<" district: "<<paddr->district<<std::endl;
}


int main(int argc, char *argv[])
{
        Person p((char *)"ivan1001", 20, 0);
        Address addr((char *)"Guangdong", (char *)"Shenzhen", (char *)"Nanshan");

        p.showAddressInfo(&addr);

        return 0x0;
}

上述,我们称class Person是class Address的友元类。

编译运行:

# gcc -o test test.cpp -lstdc++
# ./test
province: Guangdong city: Shenzhen district: Nanshan

需要注意的是:

  • 友元的关系是单向的而不是双向的。如果声明了class Bclass A的友元类,不等于class Aclass B的友元类,class A中的成员函数不能访问class B中的private成员。

  • 友元的关系不能传递。如果类class Bclass A的友元类,class Cclass B的友元类,不等于class Cclass A的友元类。



[参看]: