IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++友元知识点详解 -> 正文阅读

[C++知识库]C++友元知识点详解

1.何为友元?

类可以允许其他类或者函数访问它的非公有成员,方式是令其他类或者函数成为它的友元(需要用到friend关键字)。

2.友元分类

3.非成员函数作为友元函数

示例代码结构如下:

// Student.hpp

#ifndef STUDENT_HPP
#define STUDENT_HPP

class Student {
public:

    friend void ModifyAge( Student &stu, int value );
    Student():age(18){}
    ~Student(){}
    int GetAge(){
        return age;
    }
private:
    void SetAge( int tmp ){
        age = tmp;
    }
    int age;   
};
void ModifyAge( Student &stu, int value );
#endif /* STUDENT_HPP */

// Student.cpp

#include "Student.hpp"

void ModifyAge( Student &stu, int value ){
    stu.SetAge(value);
}
// main.cpp


#include <iostream>
#include "Student.hpp"

using namespace std;


int main( void ){
    Student a;
    cout << a.GetAge() << endl;
    ModifyAge( a, 25 );
    cout << a.GetAge() << endl;
    return 0;
}

友元声明只能出现在类定义的内部,但是在类内出现的具体位置没有限制。

并且友元不是类的成员,不受它所在区域,访问控制级别的约束(不受public,private的约束)。

特别注意:友元声明仅仅是指定了访问权限,也就是告诉Student这个类,ModifyAge可以访问age这个私有数据成员。类定义中?ModifyAge函数的友元声明,并不是普通意义上的函数声明。因此,在类定义的外部,我们单独对ModifyAge函数进行了声明(注意这里没有用friend关键字)。

如果我们没有在类的外部对ModifyAge函数进行声明,main.cpp的内容如下所示:

// main.cpp

#include <iostream>
//#include "Student.hpp"	Student.hpp替换为下面的内容


class Student {
public:

    friend void ModifyAge( Student &stu, int value );
    Student():age(18){}
    ~Student(){}
    int GetAge(){
        return age;
    }
private:
    void SetAge( int tmp ){
        age = tmp;
    }
    int age;   
};


using namespace std;

int main( void ){
    Student a;
    cout << a.GetAge() << endl;
    ModifyAge( a, 25 );			// 这里在编译时会报错,在当前文件中,找不到ModifyAge函数的声明
    cout << a.GetAge() << endl;
    return 0;
}

许多编译器并未强制要求友元函数必须在使用之前在类的外部声明。上述错误,不一定在你的编译环境中会复现。但是,出于代码的可移植性,我们最好还是在类定义的外部,单独对友元函数进行声明。

4.类是友元

示例代码结构如下:

?

// Student.hpp


#ifndef STUDENT_HPP
#define STUDENT_HPP


class Student {
public:
    friend class Teacher;
    Student():age(18){}
    ~Student(){}
    int GetAge(){
        return age;
    }
private:
    void SetAge( int tmp ){
        age = tmp;
    }
    int age;   
};
#endif /* STUDENT_HPP */
// Teacher.hpp



#ifndef TEACHER_HPP
#define TEACHER_HPP

#include "Student.hpp"

class Teacher {
public:
    Teacher() = default;
    virtual ~Teacher();
    void SetStudentAge( Student &stu, int value );
private:

};

#endif /* TEACHER_HPP */
// Teacher.cpp


#include "Teacher.hpp"


Teacher::~Teacher() {
}


void Teacher::SetStudentAge( Student &stu, int value ){
    stu.SetAge(value);
}
// main.cpp


#include <iostream>
#include "Student.hpp"
#include "Teacher.hpp"

using namespace std;

int main( void ){
    Student a;
    cout << a.GetAge() << endl;
    
    Teacher t1;
    t1.SetStudentAge(a,30);
    cout << a.GetAge() << endl;
        
    return 0;
}

5.类的成员函数是友元

示例代码结构如下:

?

// Student.hpp

#ifndef STUDENT_HPP
#define STUDENT_HPP

// 这里包含Teacher1的头文件,是因为友元声明中用到了Teacher1::
#include "Teacher1.hpp"

class Student {
public:
    friend void Teacher1::SetStuAge( Student &stu, int value );
    Student():age(18){}
    ~Student(){}
    int GetAge(){
        return age;
    }
private:
    void SetAge( int tmp ){
        age = tmp;
    }
    int age;   
};
#endif /* STUDENT_HPP */

// Teacher1.hpp

#ifndef TEACHER1_HPP
#define TEACHER1_HPP

// 注意:这里没有包含Student的头文件
class Student;  // 这里用的是不完全类型

class Teacher1 {
public:
    Teacher1();
    void SetStuAge( Student &stu, int value );
    virtual ~Teacher1();
private:

};

#endif /* TEACHER1_HPP */
// Teacher1.cpp


#include "Teacher1.hpp"
#include "Student.hpp"    // 这里包含了Student头文件
Teacher1::Teacher1() {
}


Teacher1::~Teacher1() {
}


void Teacher1::SetStuAge( Student &stu, int value ){
    stu.SetAge(value);
}
// main.cpp

#include <iostream>
#include "Student.hpp"
#include "Teacher1.hpp"

using namespace std;

int main( void ){
    Student a;
    cout << a.GetAge() << endl;

    Teacher1 t2;
    t2.SetStuAge(a,35);
    cout << a.GetAge() << endl;
    
    return 0;
}

到这里三种友元类型的示例都展示完成了。

最不好理解的就是成员函数作为友元的情况,需要组织好类的结果,不然编译时,很容易报错。

下面对第三种情况做一个总结。

类B有一个成员函数B::func(),是类A的友元,那么三者需要按照下面的顺序进行组织:

  • 首先定义类B,声明func函数,但是不能定义它。同时需要在定义类B之前,声明类A(不完整声明)。
  • 定义类A,包括对B::func函数的友元声明(#include "B.hpp")。
  • 最后定义B::func,此时它才可以使用类A的私有成员。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:05:39  更:2022-04-09 18:09:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:52:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码