【C++】C++中的友元函数和友元类

C++中的友元函数和友元类

1.友元:

问题:无论使用何种继承,子类都是无法使用父类的私有成员

解决: C++提供了一种机制,A类的内部可以直接使用B类的私有成员(还是要用B类的对象调用私有成员) ---》友元类

普通函数的内部可以直接使用某个类的私有成员 ---》友元函数

2.友元的语法规则

2.1 友元函数

分为两种情况:

  • 普通函数作为类的友元函数
  • 成员函数作为类的友元函数(写法比较复杂)
cpp 复制代码
friend 返回值 函数名(参数);
示例代码:普通函数作为类的友元函数
cpp 复制代码
#include <iostream>
using namespace std;

/*
    友元函数:分为两种
         第一种:普通函数作为类的友元函数
*/

class Cat
{
public:
    Cat(string &name,int age) : m_name(name),m_age(age)
    {
        cout<<"猫构造"<<endl;
    }
    ~Cat()
    {
        cout<<"猫析构"<<endl;
    }
    friend void show(Cat *c);
private:
    string m_name;
    int m_age;
};

void show(Cat *c)
{
    // 若不声明为友元函数时报错error: 'std::string Cat::m_name' is private within this context
    cout<<"name="<<c->m_name<<endl;
    cout<<"age="<<c->m_age<<endl;
}

int main()
{
    string name="Tom";
    Cat *c1=new Cat(name, 2);
    // 报错:error: cannot bind non-const lvalue reference of type 'std::string&'
    Cat c2("Jerry", 3); 

    show(c1);
}

/*
执行结果: 
    猫构造
    name=Tom
    age=2
*/
示例代码:成员函数作为类的友元函数
cpp 复制代码
#include <iostream>
using namespace std;

/*
    友元函数:
         成员函数作为类的友元函数
         Dog有个成员函数,该成员函数想要访问/修改猫的私有成员变量
*/

//前向引用声明:告诉编译器有定义Cat这个类
//前向引用声明的缺陷:只能告知Cat类的存在,但是这个类具体有什么成员无法得知

class Cat;

class Dog
{
public:
    Dog()
    {
        cout<<"狗构造"<<endl;
    }
    ~Dog()
    {
        cout<<"狗析构"<<endl;
    }
    void show(Cat &c);
};

class Cat
{
public:
    Cat(string &name,int age)
    {
        m_name=name;
        m_age=age;
        cout<<"猫构造"<<endl;
    }
    ~Cat()
    {
        cout<<"猫析构"<<endl;
    }

    friend void Dog::show(Cat &c);  // 声明为友元函数
    
private:
    string m_name;
    int m_age;
};

void Dog::show(Cat &c)  // 定义为友元函数,可以访问Cat类的私有成员
{
    cout<<"name="<<c.m_name<<endl;
    cout<<"age="<<c.m_age<<endl;
}

int main()
{
    string name = "小猫";
    Cat c(name,10);
    Dog d;
    d.show(c);
}

/*
执行结果: 
    猫构造
    狗构造
    name=小猫
    age=10
    狗析构
    猫析构
*/

2.2 友元类

cpp 复制代码
friend class 类名;
示例代码:友元类-某个类整体作为另外一个类的友元
cpp 复制代码
#include <iostream>
using namespace std;

/*
    友元类:某个类整体作为另外一个类的友元
*/

class Dog;

class Cat
{
public:
    Cat(string &name,int age)
    {
        m_name=name;
        m_age=age;
        cout<<"猫构造"<<endl;
    }
    ~Cat()
    {
        cout<<"猫析构"<<endl;
    }
    //声明狗这个类是猫的友元类(狗类要访问或修改猫的私有成员要猫承认是狗的"朋友")
    friend class Dog;
private:
    string m_name;
    int m_age;
};

class Dog
{
public:
    Dog()
    {
        cout<<"狗构造"<<endl;
    }
    ~Dog()
    {
        cout<<"狗析构"<<endl;
    }
    //狗里面的成员方法访问猫的私有成员
    void show(Cat &c)
    {
        cout<<"name="<<c.m_name<<endl;
        cout<<"age="<<c.m_age<<endl;
    }
    //狗里面的成员方法修改猫的私有成员
    void setCat(Cat &c, string &newname,int newage)
    {
        c.m_name=newname;
        c.m_age=newage;
    }
};

int main()
{
    string name = "小猫";
    string newname = "大猫";
    Cat c(name,10);
    Dog d;
    //狗里面的成员方法访问猫的私有成员
    d.show(c);
    //狗里面的成员方法修改猫的私有成员
    d.setCat(c,newname,20);
    d.show(c);
}

/*
执行结果: 
    猫构造
    狗构造
    name=小猫
    age=10
    name=大猫
    age=20
    狗析构
    猫析构
*/

3.特点

  • 友元不能继承,A是B的友元类,但是A的子类并不是B的友元类
  • 友元是单向的,A是B的友元,但是不能反过来
  • 友元不能传递,A是B的友元,B是C的友元,不能得出结论A是C的友元

缺点:
\quad 破坏了类的封装性

示例代码:普通函数作为类的友元函数写在类的里面
cpp 复制代码
#include <iostream>
using namespace std;

/*
    普通函数的代码写在类的里面
*/

class Cat
{
public:
    Cat(string _name,int _age)
    {
        name=_name;
        age=_age;
    }
    //声明show函数是猫的友元函数
    friend void show(Cat &other) //代码写在类的里面,是可以的,但是show依然是个普通函数
    {
        cout<<"猫的姓名: "<<other.name<<endl;
        cout<<"猫的年龄: "<<other.age<<endl;
    }
private:
    int age;
    string name;
};


int main()
{
    Cat c1("旺财",5);
    show(c1);    
}
相关推荐
虾球xz22 分钟前
CppCon 2018 学习:EFFECTIVE REPLACEMENT OF DYNAMIC POLYMORPHISM WITH std::variant
开发语言·c++·学习
津津有味道2 小时前
Qt C++串口SerialPort通讯发送指令读写NFC M1卡
linux·c++·qt·串口通信·serial·m1·nfc
让我们一起加油好吗2 小时前
【C++】list 简介与模拟实现(详解)
开发语言·c++·visualstudio·stl·list
傅里叶的耶2 小时前
C++系列(二):告别低效循环!选择、循环、跳转原理与优化实战全解析
c++·visual studio
Vitta_U2 小时前
MFC的List Control自适应主界面大小
c++·list·mfc
Dovis(誓平步青云)3 小时前
基于探索C++特殊容器类型:容器适配器+底层实现原理
开发语言·c++·queue·适配器·stack
pipip.5 小时前
UDP————套接字socket
linux·网络·c++·网络协议·udp
孞㐑¥9 小时前
Linux之Socket 编程 UDP
linux·服务器·c++·经验分享·笔记·网络协议·udp
水木兰亭13 小时前
数据结构之——树及树的存储
数据结构·c++·学习·算法
CoderCodingNo13 小时前
【GESP】C++四级考试大纲知识点梳理, (7) 排序算法基本概念
开发语言·c++·排序算法