• C++基础知识-DAY6


    1. 友元

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

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

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

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

    1. Get/set

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

     

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

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

     

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

    友元主要是用来提升效率

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

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

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

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

    (2) 关系

    a. 同类间无私处

    b. 异类间有友元

    c. 友元不是成员

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

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

     

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

     

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

     

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

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

     

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

    a. 不能定义对象

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

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

     

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

    c. 

    (6) 友元类

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

    class A

    {

    friend class B;

    public:

    private:

    }

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

    (7) 

    2.  友元结论

    声明位置

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

    友元

    友元利弊

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

    注意

    友元关系不能被继承

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

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

    3. 运算符重载

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

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

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

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

     

    对于加号上面的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加以限定来实现

    第二个例子是=

     

    4. 重载范例

    (1) 双目举例

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

     

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

     

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

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

     

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

     

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

     

    再次对功能进行扩充

     

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

     

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

  • 相关阅读:
    Golang学习开篇——Go语言优势
    Ubuntu —— 查看和开放端口
    mysql——sql语句
    python模块——xlwt
    字典容器类型使用之坑
    pandas——将sql查询结果,分几部分存入excel
    pandas 点击 excel 表格数据,跳转到 sheet2
    datetime——计算前一天的这个时间 坑
    报错总结
    nginx——部署前端
  • 原文地址:https://www.cnblogs.com/Cucucudeblog/p/11354653.html
Copyright © 2020-2023  润新知