C++基础知识-DAY6

1. 友元

      采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,,依此提供类与外界间的通信接口。

      但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,有时可以将这些函数定义为该类的友元函数,除了友元函数外,还有友元类,两者统称为友元。

      友元的作用是提高了程序的运行效率(即减少了类型和安全性检查及调用的时间开销),但他破坏了类的封装性和隐  藏性,使得非成员函数可以访问类的私有成员。

友元可以是一个函数,该函数被称为友元函数,友元也可以是一个类,该类被称为友元类。

1. Get/set

Get方法和set方法,是常见的获取数据成员的方式,比如在游戏中,任务遭到攻击后血量的减少就要用到set方法,而实时的显示就需要set方法

C++基础知识-DAY6C++基础知识-DAY6 

由于_lifeBlood是私有的,为了访问他,我们必须要做的事情就是通过函数来访问他,这就意味着,在这个过程中需要不断的压栈与出栈,那么就面临一个问题,怎么样才能提高战斗的效率呢

如果fight()内部的函数可以写成如下

C++基础知识-DAY6

 

C++基础知识-DAY6 

这样就可以省去很多压栈出栈的开销,节约成本,但是由于_lifeBlood是私有的,不可以这样访问,除此之外,由于真正在游戏中,参与fight的对象是不定的,可以是多个,所以说fight常被写成全局函数,这样就更不能直接访问私有变量了,为了解决这些问题,引入友元friend的概念,在类内声明friend void fight(Sprite &sp);

友元主要是用来提升效率

 

 

其中get方法和set方法是标准封装的结果,friend破坏了这种封装,但又带来了效率的提高

(1) 采用类的机制后实现了对数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为共有的,以此提供类与外界间的通信接口,但是,有时需要定义一些函数,这些函数不是类的一部分,但又频繁的访问类的数据成员,这时可以将这些函数定义为该类的友元函数,除了友元函数外,还有友元函数类,两者统称为友元

友元的作用是提高了程序的运行效率(即减少了类型和安全检查及调用的时间开销),但他破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员

友元可以是一个函数,该函数称为友元函数,友元也可以是一个类,该类称为友元类

(2) 关系

a. 同类间无私处

b. 异类间有友元

c. 友元不是成员

友元函数终究不是成员函数,成员中有隐参this指针,可以直接访问成员,而 友元没有,必须得通过对象来访问

友元仅是打破了外部访问中的private权限,声明为谁的友元,就可以通过谁的对象,访问谁的私有成员,一定要注意,是通过对象访问的

C++基础知识-DAY6

 

C++基础知识-DAY6 

(3) 友元函数(全局做友元函数)

C++基础知识-DAY6

 

C++基础知识-DAY6 

(4) 类成员做友元,涉及到一个前向声明的问题

C++基础知识-DAY6

 

C++基础知识-DAY6 

C++是先声明,后使用,由以上,在用友元函数的时候,其是没有对magagePoint有任何的声明,因此我们需要加一个前向声明。前向声明是一种不完全类型的声明,其是不能定义对象的,但是可以定义指针和引用,做参数和返回值,仅用作函数的声明

你中有我,我中有你的情况是最难确定顺序的,如上,getDistance必须要看到了其定义才能用,而对于ManagePoint中的Point只需要class Point前向声明即可

C++基础知识-DAY6

 

C++基础知识-DAY6 

(5) 前向声明,是一种不完全声明,其特点为

a. 不能定义对象

如最开始的前向声明class Point 中,如class Point a,b,c等声明对象的行为是不可以的

b. 可以用于定义指向这个类型的指针或引用

C++基础知识-DAY6

 

C++基础知识-DAY6 

前两种都是可以的,可以定义指向这个类的指针或引用

c. 

(6) 友元类

当希望一个类中所有成员函数,均可存取另一个类的私有成员时,可以将该类声明为另一个类的友元

class A

{

friend class B;

public:

private:

}

在实际工作中,程序员喜欢友元类

(7) 

2.  友元结论

声明位置

友元声明以关键字friend开始,他只能出现在类定义中,因为友元不是类授权的成员,所以他不受其所在类的声明区域public,private和protected的影响,因此我们选择把所有友元声明组织在一起并放在类头之后

友元

友元利弊

友元不是类函数,但是他可以通过对象访问类中的私有成员,友元的作用在于提高程序的运行效率,但是,他破坏了类的封装性和隐蔽性,使得非成员函数可以访问类的私有成员

注意

友元关系不能被继承

友元关系是单向的,不具有交换性,若类B是类A 的友元,若类A不一定是类B的友元

若类B是类A 的友元,类C是类B 的友元,则类C不一定是类A的友元

3. 运算符重载

运算符重载的本质是函数重载,函数名即operator x

但凡涉及到自定义类型,想要跟普通数据类型一样的操作体验,就需要重载

友元重载,即全局函数重载

对于运算符重载,我们首先举两个例子,第一个是+

C++基础知识-DAY6 

对于加号上面的const是否要加的问题, 对于int a; int b; int c; (a=b)=c是可以的,而(a+b)=c则是不可以的,但是对于对象a,y来说,这种赋值是可以的,相当于将对象x,y加起来赋给一个匿名空间,这样是不好的,因此我们加了一个const使其直接无法编译过去

这个就是const做返值修饰符的概念,

C++引入引用的概念后,表达式可以被赋值的现象出现了,有的表达式可以被赋值,有些表达式则不可以被赋值,比如对于int a; int b; int c; (a=b)=c是可以的,而(a+b)=c则是不可以的,重新的运算符是否会导致表达式可以被赋值应该以基础类型为准,返回类型通常通过加const加以限定来实现

第二个例子是=

C++基础知识-DAY6 

4. 重载范例

(1) 双目举例

对于+=的情况,我们可以先写成如下

C++基础知识-DAY6 

但是这样会报错,原因是ca+=(cb+=cc)中,cb+=cc会产生一个临时变量,临时变量只能赋给const,

C++基础知识-DAY6 

(2) 单目列举(a++,++a)

首先和int 类型的-n做类比

C++基础知识-DAY6 

这样可以编译过去,但是如果加上其他的功能,比如说-n=10这种在int类型中是编译不过去的,类比-n=10,我们有如下的代码

C++基础知识-DAY6 

在编译过程中,我们发现-cc=Complex(-10,0);是可以编译过去的,这个不是我们要的,因此我们可以引入const做返值修饰符,专门解决这个问题

C++基础知识-DAY6 

再次对功能进行扩充

C++基础知识-DAY6 

但是-(-c)是编译不过去的,相当于返值再次调用了operator-函数,相当于(c.operator-()). operator-();这里出现的问题是c.operator-()返回了一个const对象,const对象再调用一个非const函数,所以说会报错,因此将函数写成const

C++基础知识-DAY6 

(3) 在整个程序中我们使用到几次匿名对象,匿名对象是可以被赋值的,可以发起成员函数的调用,

 

上一篇:剑指 Offer 12. 矩阵中的路径


下一篇:Scrum冲刺-day6