重学C++系列之友元

一、什么是友元

        在C++中,为了提高程序的效率,在一些场景下,引入友元,但同时类的封装性就会被破坏。

二、怎么实现友元

        友元关键字(friend)


// 在类中声明另一个类的成员函数来做为友元函数
// 以关键字(friend)开头:比如friend 返回值类型 类名::类成员函数(参数列表)
friend void A::test(Test &t);



// 全局函数做友元函数

// friend 普通函数的声明

friend void print(Test &t);


// 友元类,要在另外一个类中声明
class 类名1
{


    friend class 友元类名;    // 在类里面声明友元类
}

三、友元的特点

        1、友元关系是单向的,不具备交换性。

        2、友元关系不能被继承。

        3、友元关系不具有传递性。

        4、友元不是类成员,但是它可以通过对象访问类中私有成员,友元作用在于提高程序的运行效率,但是,它破坏了类的封装和数据隐藏性。除非调用访问私有成员变量的频率频繁,才会考虑牺牲封装和数据隐藏性,来换取运行效率。

        5、模板类中声明的友元函数必须要指定具体类型才行,不能声明一个友元函数模板。

四、案例

        1、 在类中声明另一个类的成员函数来做为友元函数

#include 

using namespace std;

class Base;
class Test
{
public:
    // 不可以在类中实现,只能在类外实现, 此时编译器还没有编译Base类,无法识别出友元
    void show(Base &other); 
    // {
    //     cout << "a = " << other.a << endl;
    // }

};

class Base
{
private:
    int a;
public:
    Base(int a = 0)
    {
        this->a = a;
    }
    friend void Test::show(Base &other);
};

// 不可以在类中实现,只能在类外实现,此时编译器已识别出友元
void Test::show(Base &other)
{
    cout <<"void Test::show(Base &other)" << endl;
    cout << "a = " << other.a << endl;
}


int main()
{

    Base A(10);
    Test test;
    test.show(A);


    return 0;
}

重学C++系列之友元_第1张图片

 

        2、全局函数做友元函数 

#include 

using namespace std;


class Base
{
private:
    int a;
public:
    Base(int a = 0)
    {
        this->a = a;
    }
    // 全局函数声明为友元函数
    friend void show(Base &other);
};

// 全局函数声明为友元函数
void show(Base &other)
{
    cout << "void show(Base &other)" << endl;
    cout << "a = " << other.a << endl;
}


int main()
{

    Base A(10);
    show(A);
   


    return 0;
}

重学C++系列之友元_第2张图片

        3、友元类

#include 

using namespace std;

class Test; // 先声明一个类Test

class Base
{
private:
    int a;
public:
    Base(int a = 0)
    {
        this->a = a;
    }
    friend class Test;  // 把类Test声明为友元类
};

class Test
{
public:
   
    void show(Base &other)
    {
        cout << "void Test::show(Base &other)" << endl;
        cout << "a = " << other.a << endl;
    }

};

int main()
{

    Base A(10);
    Test test;
    test.show(A);


    return 0;
}

重学C++系列之友元_第3张图片

        4、模板类中声明的友元函数必须要指定具体类型才行,不能声明一个友元函数模板。

#include 

using namespace std;



template 
class Test
{
private:
    T a;
public:
    Test(T a = T())
    {
        this->a = a;
    }
    // 定义一个友元函数模板,编译不能通过
    friend ostream& operator << (ostream& output, const Test &other);


};

template 
ostream& operator << (ostream& output, const Test &other)
{
    output << "a = " << other.a << endl;
    return output;
}



int main()
{
    Test A(10);
    cout << A << endl;
    


    return 0;
}

重学C++系列之友元_第4张图片

        改正:

#include 

using namespace std;



template 
class Test
{
private:
    T a;
public:
    Test(T a = T())
    {
        this->a = a;
    }
    // 指定友元函数的具体模板类型,但是这样模板类的作用几乎失效
    friend ostream& operator << (ostream& output, const Test &other);


};

// 指定模板类为int类型
ostream& operator << (ostream& output, const Test &other)
{
    output << "ostream& operator << (ostream& output, const Test &other)" << endl;
    output << "a = " << other.a;
    return output;
}



int main()
{
    Test A(10);
    cout << A << endl;
    


    return 0;
}

重学C++系列之友元_第5张图片

五、总结

        友元的作用是在某些场景提高程序的效率,但是同时也破坏了类的封装性和数据的隐藏性。声明友元时,要注意友元的位置,编译器是否已经识别或者编译了所声明的友元,如果没有,就会报错,所以可以采用再类中定义友元,把友元类的函数在类外实现,具体例子看上面的案例。

你可能感兴趣的:(C++语言设计,c++)