zoukankan      html  css  js  c++  java
  • 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) 在整个程序中我们使用到几次匿名对象,匿名对象是可以被赋值的,可以发起成员函数的调用,

  • 相关阅读:
    Count and Say leetcode
    Find Minimum in Rotated Sorted Array II leetcode
    Find Minimum in Rotated Sorted Array leetcode
    Search in Rotated Sorted Array II leetcode
    search in rotated sorted array leetcode
    Substring with Concatenation of All Words
    Subsets 子集系列问题 leetcode
    Sudoku Solver Backtracking
    Valid Sudoku leetcode
    《如何求解问题》-现代启发式方法
  • 原文地址:https://www.cnblogs.com/Cucucudeblog/p/11354653.html
Copyright © 2011-2022 走看看