首页 > 其他分享 >24.友元函数

24.友元函数

时间:2022-09-30 19:23:07浏览次数:45  
标签:24 友元 函数 class Building public friend

1.友元

  类的主要特点之一是数据隐藏,即类的私有成员无法在类的外部(作用域之外)访问。但是,有时候需要在类的外部访问类的私有成员,怎么办?

  解决方法是使用友元函数,友元函数是一种特权函数,c++允许这个特权函数访问私有成员。这一点从现实生活中也可以很好的理解:

  比如你的家,有客厅,有你的卧室,那么你的客厅是Public的,所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的闺蜜好基友进去。

  程序员可以把一个全局函数、某个类中的成员函数、甚至整个类声明为友元。

1.1.友元语法

● friend关键字只出现在声明处

●其他类、类成员函数、全局函数都可声明为友元

●友元函数不是类的成员,不带this指针

●友元函数可访问对象任意成员属性,包括私有属性

class Building;
//友元类
class MyFriend{
public:
	//友元成员函数
	void LookAtBedRoom(Building& building);
	void PlayInBedRoom(Building& building);
};
class Building{
	//全局函数做友元函数
	friend void CleanBedRoom(Building& building);
#if 0
	//成员函数做友元函数
	friend void MyFriend::LookAtBedRoom(Building& building);
	friend void MyFriend::PlayInBedRoom(Building& building);
#else	
	//友元类
	friend class MyFriend;
#endif
public:
	Building();
public:
	string mSittingRoom;
private:
	string mBedroom;
};

void MyFriend::LookAtBedRoom(Building& building){
	cout << "我的朋友参观" << building.mBedroom << endl;
}
void MyFriend::PlayInBedRoom(Building& building){
	cout << "我的朋友玩耍在" << building.mBedroom << endl;
}

//友元全局函数
void CleanBedRoom(Building& building){
	cout << "友元全局函数访问" << building.mBedroom << endl;
}

Building::Building(){
	this->mSittingRoom = "客厅";
	this->mBedroom = "卧室";
}

int main(){

	Building building;
	MyFriend myfriend;

	CleanBedRoom(building);
	myfriend.LookAtBedRoom(building);
	myfriend.PlayInBedRoom(building);

	system("pause");
	return EXIT_SUCCESS;
}

    [友元类注意]
1.友元关系不能被继承。
2.友元关系是单向的,类A是类B的朋友,但类B不一定是类A的朋友。
3.友元关系不具有传递性。类B是类A的朋友,类C是类B的朋友,但类C不一定是类A的朋友。

思考: c++是纯面向对象的吗?

如果一个类被声明为friend,意味着它不是这个类的成员函数,却可以修改这个类的私有成员,而且必须列在类的定义中,因此他是一个特权函数。c++不是完全的面向对象语言,而只是一个混合产品。增加friend关键字只是用来解决一些实际问题,这也说明这种语言是不纯的。毕竟c++设计的目的是为了实用性,而不是追求理想的抽象。
                                                                                                                                                                                                                                --- Thinking in C++


2.视频内容

程序1(全局函数的友元):

#pragma warning(disable:4996)
//2022年9月26日20:02:07
#include <iostream>
using namespace std;
#include <string>

class Building
{
    //声明这个全局函数为Building类的友元函数
    friend void GoodGay(Building &bd);
private:
    string woshi;
public:
    string keting;

public:
    Building()
    {
        keting = "客厅";
        woshi = "卧室";
    }
};
 
void GoodGay(Building& bd)
{
    cout << "好基友访问:" << bd.keting << endl;
    cout << "好基友访问:" << bd.woshi << endl;
}

void test01()
{
    Building my;

    GoodGay(my);
}

int main()
{
    test01();

    system("pause");
    return EXIT_SUCCESS;
}

输出结果:

好基友访问:客厅
好基友访问:卧室
请按任意键继续. . .

重点难点:

1	友元的作用:在类外访问类的私有成员
2	友元分:友元函数,友元类,成员函数的友元函数
3	在普通函数或类的前面加上friend,在类中声明
4	友元类不能被继续,友元是单向,友元没有传递性

程序2(友元类):

#pragma warning(disable:4996)
//2022年9月26日21:00:093
#include <iostream>
using namespace std;

class Building
{
    //声明GoodF类为友元类
    friend class GoodF;
public:
    string keting;
private:
    string woshi;

public:
    Building()
    {
        keting = "客厅";
        woshi = "卧室";
    }
};

class GoodF
{
public:
    void func(Building &bd)
    {
        cout << "访问: " << bd.keting << endl;
        cout << "访问: " << bd.woshi << endl;
    }
};
//1.通过传入参数来访问类的私有成员
void test01()
{
    Building bd;
    GoodF f;
    f.func(bd);
}

int main()
{
    test01();
    system("pause");
    return EXIT_SUCCESS;
}

输出结果:

访问: 客厅
访问: 卧室
请按任意键继续. . .

程序3:

#pragma warning(disable:4996)
//2022年9月26日21:00:093
#include <iostream>
using namespace std;

class Building
{
    //声明GoodF类Building类的友元类
    friend class GoodF;
    friend class GoodF2;
public:
    string keting;
private:
    string woshi;

public:
    Building()
    {
        keting = "客厅";
        woshi = "卧室";
    }
};
class GoodF
{
public:
    void func(Building &bd)
    {
        cout << "访问: " << bd.keting << endl;
        cout << "访问: " << bd.woshi << endl;
    }
};
//1.通过传入参数来访问类的私有成员
void test01()
{
    Building bd;
    GoodF f;
    f.func(bd);
}

//2.通过类内指针来访问类的私有成员
class GoodF2
{
public:
    Building *pbu;

public:
    GoodF2()
    {
        pbu = new Building;
    }
    void func()
    {
        cout << "访问: " << pbu->keting << endl;
        cout << "访问: " << pbu->woshi << endl;
    }
};
void test02()
{
    GoodF2 f;
    f.func();
}

int main()
{
    test02();
    system("pause");
    return EXIT_SUCCESS;
}

输出结果:

访问: 客厅
访问: 卧室
请按任意键继续. . .

程序4:

#pragma warning(disable:4996)
//2022年9月26日21:00:093
#include <iostream>
using namespace std;

class Building
{
    //声明GoodF类Building类的友元类
    friend class GoodF;
    friend class GoodF2;
public:
    string keting;
private:
    string woshi;

public:
    Building()
    {
        keting = "客厅";
        woshi = "卧室";
    }
};
class GoodF
{
public:
    void func(Building& bd)
    {
        cout << "访问: " << bd.keting << endl;
        cout << "访问: " << bd.woshi << endl;
    }
};
//1.通过传入参数来访问类的私有成员
void test01()
{
    Building bd;
    GoodF f;
    f.func(bd);
}

//2.通过类内指针来访问类的私有成员
class GoodF2
{
public:
    Building* pbu;

public:
    GoodF2()
    {
        cout << "无参构造" << endl;
        pbu = new Building;
    }
    void func()
    {
        cout << "访问: " << pbu->keting << endl;
        cout << "访问: " << pbu->woshi << endl;
    }
    //拷贝构造
    GoodF2(const GoodF2& f2)
    {
        cout << "拷贝构造" << endl;
        //1.申请空间
        pbu = new Building;
        ////2.拷贝数据
        //pbu->keting =
    }
    ~GoodF2()
    {
        cout << "析构函数" << endl;
        if (pbu != NULL)
        {
            delete pbu;
        }
    }
};
void test02()
{
    GoodF2 f;
    f.func();

    GoodF2 f2 = f;
}

int main()
{
    test02();
    system("pause");
    return EXIT_SUCCESS;
}

输出结果:

访问: 客厅
访问: 卧室
拷贝构造
析构函数
析构函数
请按任意键继续. . .

程序5:

#pragma warning(disable:4996)
//2022年9月30日18:37:34

#include <iostream>
using namespace std;

//1.编译器直到类的声明,不知道类的结构
class Building;//声明类
class GoodGay
{
public:
    void func(Building& bud);
};

class Building
{
    //声明GoodGay类的成员func()成为BUilding类的友元函数
    friend void GoodGay::func(Building &bud);
public:
    Building()
    {
        keting = "客厅";
        woshi = "卧室";
    }

public:
    string keting;
private:
    string woshi;
};

void GoodGay::func(Building& bud)
{
    cout << "访问:" << bud.keting << endl;
    cout << "访问:" << bud.woshi << endl;
}

void test()
{
    Building bud;
    GoodGay GF;
    GF.func(bud);
}

int main()
{
    test();
    system("pause");
    return EXIT_SUCCESS; 
}

输出结果:

访问:客厅
访问:卧室
请按任意键继续. . .

标签:24,友元,函数,class,Building,public,friend
From: https://www.cnblogs.com/codemagiciant/p/16745897.html

相关文章

  • ABC246
    FourPointsGetCloserCoupon2-variableFunctionBishoptypewriterGameonTree301?Queries......
  • JS 柯里化函数随笔
    模拟实现constslice=Array.prototype.slice;constcurryMaker=function(fn,len){constcurriedArgs=slice.call(arguments,2);returncurry.apply(this......
  • pandas中绘图函数plot的使用以及cumsum()函数
     从最简单的开始,如果要绘制一条数据的线性图。因为Series和DataFrame都有一个用于生成各类图表的plot方法。对于一条Series数据,直接plot()就能获得一张线性图了data=......
  • python-当函数赋给变量时带括号与不带括号的区别
    python-当函数赋给变量时带括号与不带括号的区别参见下面的例子:deftest():print("callthetestfunc")return0p=testprint("type(p):",type(p))pr......
  • Oracle 的nvl函数和nvl2函数用法
    空空Ryan nvl()函数和nvl2()函数如果你某个字段为空,但是你想让这个字段显示0,可以使用nvl(字段名,0),当然这个0也可以换成其他东西,如:1,2,3…… 一 NVL(表达式1,......
  • 怎样给函数设置多个返回值
    一、使用元组实现1.1使用ValueTuple实现ValueTuple命名为元组(在C#7.1中可用),优点是它最简洁,不可变且易于构造。private(doublefirst,doublesecond)GetHeight(){......
  • 函数集合
    01提取不同文件夹下同名文件点击查看代码defselect(dir,name):importosimportshutillist1=[]list2=[]dd=''forroot,dirs,fil......
  • C语言:字符串连接函数
    #include<stdio.h>#include<string.h>voidlianjie(chara[],charb[],charc[]){inti,j,len1=strlen(a),len2=strlen(b);for(i=0;i<len1;i++)c[i]=......
  • JavaScript箭头函数的使用以及和普通函数之间的使用
    箭头函数的使用以及和普通函数之间的转换// 第一种不带参数    // var one = function(){    //   return 'I am one'    // }    var......
  • sql排序函数 rank() / dense_rank()
    Rank排名函数1、rank()按照某字段的排序结果添加排名,但是他是跳跃的、间断的排名partitionby子句按照对应字段将结果集分为多个分区,然后orderby子句按分数对结果集进......