- 类的权限管控
- 类的内部和类的外部的理解
- public和private
- protected
- 权限访问的好处
- 访问权限的思想对架构师尤为重要
- 访问权限牺牲了一定的效率
- struct和class在默认情况下访问权限的区别
- 先全部禁掉再按需打开的理念
- struct和class交叉继承:远古大神
- 模板之后用的全是class
- class和struct的一个剩余的小区别
- C的struct和C++的struct是不一样的
- 常函数
- multiply也遵循先全禁再按需打开的思想
- 类不占内存
- 类的前置声明
- inline的进一步理解
- 应该用不怕把类写得太长
- inline如果写外面,要写在下面
这里有个概念,你首先要理解什么是类的内部和类的,外部类的外部它其实就是外部吗?就是除了类的内部之外的东西。那么什么是类的内部呢?你的类的内部,你不要以为你的方法写在类的外面,那么它就是类的外部了这不对,就是你类里面的方法的那个声明,然后你声明的那个函数,它也是属于类的,也是属于类的。内部的就说你的方法也是你在类里面写的方法,它虽然在外面写,他是写在外面的,函数体是写外面的,但是它也是属于类的内部的。
为什么是这样的,因为比如说你定一个类,这个类叫person,然后你在外面写它这个类里面的方法的时候,你是不是用了person,然后两个冒号再写这个方法,那它就是在这个类类的里面的,因为你是用了person,然后冒号,冒号方那个类,那个那个方法的嘛,所以它肯定就是在类的内部的,只不过你这写的外面而已,它本质上它是属于类的内部的东西。
你会发现就是你这个类里面,比如说你这里面有两三个方法是不是,然后你这两三个方法你写在外面了,然后这两三个方法之间互相调用,你是可以直接用函数名的,不用什么什么的,什么其他乱七八糟的,比如说你在比如说你类里面有方法一,方法二,方法三,然后你方法一,方法二,方法三在外面定义的吗?你如果要在外面定义的时候,你在那个你的方法一里面调用了方法二,或者说你的方法二里面调用了方法一。你直接在方法一里面用方法二的函数就行了,为什么这样是可以的呢?其实这个很简单,很容易理解的,为什么呢?你想想看,你在方法里面是不是可以随便调用那个你的类里面的属性,它本质上你调用类里的属性,你是本质上就是用了this,然后一个箭头,然后加你类里面的属性去用是不是。
所以所以这就很正常,你可以推导,那你类里面的方法,你是不是也是一样的,也是可以用个this,然后加个箭头,然后去调用这个方法是不是就,所以你在方法里面,你去用你的类里面的其他方法也是可以用,肯定是可以用的,它本质上也是用this,然后加个箭头,然后那个方法调用的函数嘛,只不过它this省略掉吗嘛,可以直接所以它就可以直接这样用嘛,是不是这很容易理解的。
public和private这个private它这个权限是对内完全不设防,对外完全设防,怎么说呢,就是你在,就是你如果是在方法里面,你在你的那个,就比如说你private了一个,首先就是从先是看成员变量吧,你如果是在,你如果把这个成员变量给private掉了,那么你你在外面再累以外,你是不能用它了,但是在类以内的东西,比如说你用了那个方法,你用了一个类的方法,然后那个方法里面用到了他,那么是可以的,然后你在外面再用这个方法,那是可以的。
你在是从方法成员,方法类的成员方法角度去看,如果你把这个成员方法,比如说这个方法一,你把他pass掉了,那么你在累以外是用不到,用不了他是不能用他的,但是呢,你如果这个private的这个方法一拿,他被方法二调用了,然后方法二呢,他不是在private的里面的,他是在public外面的,那就那么你在外面,你在类以外的东西去调用方法,那么其实就可以调用方法一。
总的来说就是你如果把一个东西private掉了,那么这个东西只能在类里面的东西去用了,比如说,你把那个一个成员变量派别的把一个成员方法拍比掉了,那么你这个pad的成员的成员方法呢,只能在你类里面的方法里面去调用它了,只能在你类里面的那个方法去里面去,只能在你类里面public那里的方法啊,也不一定是public的里面的方法,反正就是只能是在类里面的那个方法去调用它这个成员变量和成员函数,然后再用,然后你如果要要外面,你如果要用那个private,那个如果要在外面用pa
你只能是这样,间接的在外面调用这个public里面的那个方法,然后那里那个public里面的方法调用了private里面的方法,这样才能够间接的调用这个private里面的方法跟成员总结一下,就是你如果把一个成员变量和成员卡放到类里面了,把它放到private里面了,那么你类以外的东西,你就别想去访问他了,你只能够你类以外的东西,你只能访问public的东西,而你如果把你的这个类里面的private的那些东西,通过public的方法去调用它的,然后你再通过类以外的东西去调用这个public的这个方法,那么你就可以间接去调用private里面的方法的成员。
protected然后还有一个就是protect protect就是介于public跟private之间的,Private是管的最严的,Public是管的最松的,Protect介于这两者之间,然后其实介于这两者之间呢,不不一定只有price,不一定只有protect,可能还有其他两三个,但是一般情况下不会超过三四个,然后这个public跟private跟protected,这三个一般是很多语言都支持的一个访问权限的的一个关键字,然后可能中间呢,除了protect还有其他的可能,但是其他原因可能还有其他的,或者说还有其他的一些东西,介于中间的这些嘛,但是一般不会超过,一般不会超过三四个。
对,这个访问权限啊,它跟cost是一样的,它是语法层面上的一个保护,就是说,它硬件上面并没有设置这样的一个权限的,只是它编译器你设计的编译器语法上面帮你做了一个这样的一个保护,就你编译的时候都不通过,但是你如果强改是可以改,只不过编译器那里立了块警告牌给你,就跟cost是一样的,是语法层面的保护,你硬要去打开它,一定要去用它是可以。
权限访问的好处这个权限访问权限,它带来的灵活性,还有安全性,就我们为什么说灵活呢?因为你之前只能用cos的去实现,只读是吧,你不能实现止血,那你这个时候你用那个访问权限,你就可以实现只读跟止血,就你把你要那个,比如说拿age举例,你把age这个变量放到private里面去,但是你把使用H的那个方法放到public外面去,然后你使用age方法分成两个,一个是读H一个是写a。写ag很简单,你写ag那个函数参数里面,你放放个参数传进去,传进去,然后写个函数体,函数体里面写的只那个this,只这样的age,然后等于什么?然后要等于,那就你传,传参,参传的那个参数就可以直接只写,只读的话,你写个函数体如一看就成了。所以就是你把age这个本身放到了private里那里去,然后。
然后这个使用APP的方法放到public外面去,那么你就可以实现只读只写,那么你如果一旦不想让用户实现只读或只写,那你就把这个方法给去掉就行了。H本身是锁住了,用户是用不了,但是你你可以给用户提供一个使用H的一个只读的一个方法,还有一个止血的方法读取,可以给H提供一个读取方法,一个写入的方法,那么你如果只提供写入方法,不提供读取方法,那你就只读。啊,那你就只写,如果你只提供只写入的话,不提供只你,如果你只提供只图方法,不提供只写的方法,那你就,那你就只写是吧,总的意思是说,他把这个里面age放到了private里面去,把使用它的方法放到public里去,这样的话,你就一般都是用public里面的方法去调用就行了,而不用直接调用它的这个变量,直接用你调用这变量的方法去用。
这样既灵活又安全,你只用给用户提供方法,方法是public,这里这这种这种用法在c shop里面是非常常见的。
访问权限的思想对架构师尤为重要访问权限的思想在架构师里面尤为凸显,就架构师的话,一般就是帮你把架构假好,假好骂,他就会帮你设置一些访问,他就着重要考虑访问权限的问题,就是什么层级的人该了解什么什么,乘机人他有权限访问什么,把架构一层一层里好,然后给你们这些不同层级的去写代码,然后其实这是第一点。第二点是C加加的这个访问权限,包括所有高级语言的访问权限。他是以牺牲的效率为代价的,所以为什么C没有C,首先一,他C是更比C加更加强调性能,然后没有那么强调业务逻辑,只是强调底层逻辑,所以他就没必要牺牲,那这个性能去做访问权限。
访问权限牺牲了一定的效率然后C加加的话,他就偏业务了,所以它的代码量会很大,然后可能会多人开发是巴西可能就是少人开发了虾,就是多人开发,所以他就注重注重到访问权限,而且是偏业务了,但是访问权限,他终究还是以牺牲了效率为代价的,所以他多多少少也会牺牲一点效率,你你就比如说最突出的一点,就是你本来可以直接这个访问H的,但是你现在把H放到private里面去了,然后你用了public里面的方法调用了里面你。Private age,这是不是就多了一步?你是不是多了一步,通过方法才能去访问这age,而不能直接访问age,所以这就肯定是多了一步,所以它肯定是以牺牲了一定的效率为基础,所以任何的东西,只要有好处,绝对也也有不好的东西,这就是访问权限,它虽然有访问权限,但是它牺牲了一定的效率,它没有,既然没有的话,效率就更高。
我们在Linux内核里面看到那个structure里面很奇怪,就是他struck里面有个点,什么什么等于什么什么点什么什么等于什么?这个其实就是就是CC,它扩展的语法就是C语言本身是不支持的,他是GCC扩展出来的语法,他是一个初始化是,就是你结构体吗?你的结构体要初始化,你要把里面的一个东西,一个东西都给初始化掉,那么你就是这样用的。所以这个东西struck里面括号点什么什么等于什么点,什么什么等于什么?这其实就是一个struck的一个初始化来了,这是C语言本身没有了,是GCC扩展出来的语法,他这么写就是为了把里面的一个一个去初始化了,这样囊括这些就方便一点。
struct和class在默认情况下访问权限的区别这徐佳佳里面这个类呀,你如果不写,他就默认他也是private。
然后如果用的是struck的话,它默认的就是public,为什么?因为你在用struck之前就根本没有class嘛,所以根本没有权限的这个概念,所以它就默认是public,但当你呢,他也是为了向C金融,但当你用了那个C加加里面class之后,它它就CAD里面就引入了private吗?那既然那我那么就说我既然引入private,那我class又心累,那我为什么不默认是private呢?所以它是默认是private。
这里朱老师解释了一下,你他理解为什么他也觉得是在class里面,默认private就是豪,这他,他以那个SPL库为例库里面他里面他很多的那个时钟默认都是关闭的,你用哪个你再开哪个。然后这个的话就是一个避免浪费的一个理念,你用哪个在开哪个,跟private一样,你class里面默认是private,你默认是哪个,你再去top哪个,就你默认是哪个,你再去用哪个就不是,就是你要用哪个你再去,你再去开哪个。是不是,这样的话就有个避免浪费,所以他是先先是默认private,你要用公开,你再把它公开掉。
先全部禁掉再按需打开的理念所以他这个默认的差别就是说,它默认了你所一开一开始所有权限都是关闭的,那你要使用它权限,你打开它要用哪个打开哪个的权限,这种理念才是比较合理的。
那么怎么打开呢?两种方法,第一种你把那个东西放到她里面去,第二种方法就你给这个东西设计一个嗯,读取跟写入两个方法,这两个方法把它放到pub里去。
struct和class交叉继承:远古大神然后还会有一种比较少见的情况,就是class跟struck交叉继承,这是远古大神写下来的,他当时可能是从struck过渡到class的时候写,他当时可能是这样一个情况,我们现在写代码就不要这么写。但是,但是如果当到遇到这种情况怎么样,他的权限是遇到这种情况怎么办呢?他的权限是由子类去决定的。
就是说此类是什么默认的权限,那么它的这个权限就是什么,就是默认的权限是取决于此类的。
模板之后用的全是class后面使用模板的时候呢,基本上全部用的都是class,不可能出现strong,这里会很奇怪,Strong跟class不是一模一样的吗?为什么模板的时候,他用的是只能用class,不能用strong,原因很简单,因为模板它是在出现了class之后出现的。
class和struct的一个剩余的小区别这个class he struck还有一个小区别,就是初始化这块,如果你直接家里面用的是structures,去订一个类,那么如果你里面没有构造函数,那么它就可以用si里面那个初始化是就是用那个,就是用那个刚刚说的什么里面的只有一个点的什么什么,等于什么点什么什么等于什么就初始化,但是你如果一旦你的这个类里面用了构造函数了,那么你这个structure就不能那样子初始化了。
C的struct和C++的struct是不一样的C的,里面的struck跟C加加里面的struck是不一样的。
常函数这个C加加里面的长函数的意思就是说,他这个类里面,他那个方法方法,它不能够去修改它类里面那个属性,它可以读取,但是不能修改,不能修改它类里面的属性,像这种函数就叫做常函数,长函数的,一般是在那个函数名后面加个cost,这个常函数的用法是什么呢?一般情况下是跟cos结合在一起,用的,就是比如说你写了一个函数,这个函数不是类里面函数啊。就是外面的是内,外面的函数啊,这外面的函数呢,它用到了一个传参,它传参传的是一个cost person and pn,这个时候呢,意思就是说你不能够改变它那个PN,就是你传进来的那个东西里面的那个的值,所以它前面那个cos修饰。
他前面用了cos的去修饰的话,那么他这个函数里面调用的,它这个类里面的方法就必须得是常函数,而不能够是不是常函数,必须得是常函数,比如说你调用了一个pn.popn.h get,这批n.hkipn.h的话,如果不是常函数,那么它就会报错,必须得是常函数才能够工作,因为你在这个函数,你在这个这个函数的。就是你在你在外面的这个函数,它的船舱写个cost,所以这个时候常函数就派上用场了,你必须得要用用的时候呢,如果前面一旦加了cost,那么里面的函数必须得是常函数,常函数的话就是要在前面加cost,就是说意思就说这个函数不能够改变它的里面的类里面的属性的值。
这个不能改变它类里面属性的值,跟它那个函数里面传的那cost person and pn,那cost不能改变那个指针里面对应的那个值,这其实是有点错位的,它可能有点参差的,不是完全对应的,但是C加加语法就规定,你如果一旦前面的这传参你全是cost,那么你里面就用长函数了,就是必须得是这样子。
这个cost常函数就是你不单单是不能修改它类里面的private的函数的属性,也不能修改类里面的public的属性,只要是类里面的所有的属性都不能修改的。
multiply也遵循先全禁再按需打开的思想这个multiple也是遵也是遵循了一种设计思想,就是先全部进了,再按需打开的一个思想。
类不占内存对你在写那个你在PP里面写那个类的时候啊,那个类是不占内存的吧。
就是类本身是跟结构体一样,它不占内存的,你是把这结构体实例化,你把这个类对象化,这样之后它才能占内存,它它那个创建出来的对象还是占内存的。
就是说把类给实例化,没有对象化这个说法,就把类给实例化才能够那个实例化之后的那个对象才是占内存的。
你可以理解为就是在HP里面写的那个class类呀,它是类的一个声明,所以它这个并没有内存,它只是声明,就跟shocked一样,它只是声明,然后真正定义这个类是在那一个CPP里面去把它填充了,实例化填充了,那个才真正把类定义出来了,定义成一个对象。
哦,刚刚说错了那个类的定义呀,并不是你把它在PPT里面填充实例化了之后,能对象那个就是对象了,那个就不叫类的定义了,类的定义是说你在另外一个CPP文件里面,你把它那个类里面的方法,就把那个函数体,它不是写到外面去吗?就是就是你类里面的那些方法,他是不是也要定义写到外面,但是它是类的里面啊,但是只不过写到外面去而已。在那个CPP文件里面,那些方法的展开都写了里面内容,这个才是定义,然后而我刚刚说说错了,刚刚那个对象并不是定义那个是在使用类的,把类给填充了,然后给实例化成对象的那个,不是定义,那个是创建对象的定义,是指说那个方法在另外CPP里面写出来。
类的前置声明Or c加加里面累,他还有个前置声明,就是说比如说你这个可person这个类啊,你前置声明呢,他就把所有细节都隐掉了,隐藏掉了,直接是一个class person封号,这个东西有什么用呢?这个前置声明,因为C加加他所有的代码都是面向对象去编程的吗?你基本上钱没每走一步都要用到一个类或类里面可能又夹着其他的类,所以是类与类之间是很很多类的,很多各类在里面的。万一你在用到这个类的时候呢,这个类还没有声明就还没有,你还没有那个,因为函数是从上到下执行的嘛,所以你用到这个,你执行到这一步函数,可能你用到这个类,它在后面才声明啊,那你这个时候你这个编辑器就不知道嘛,它不知道是什么东西,所以你就要需要把这个类都放到前面,先声明一遍,然后在后面又搜才知道哦,原来是它这个类,它是一个类要用了它是个类来的。
所以说就是说他这个这个class person分号,这个很简短的一个东西,它声明了之后,你放到前面,那么他就每次用,因为然后他下面可能类类之间的用互相用的是很交错,交错复杂的,然后可能后面后面才用,还才有,才有它的整个一个大的一个,这个普通的类的一个声明出来,那你就提前在前面声明一下,先告诉编译器,哦这是一个类,所以这个简单的class person分号就放到前面,先告诉编译器,哦这是一个类先声明,以免她的泪出现了后面,然后你在前面用到它了。
是说代码是从上到下执行的,然后编译器他会做类型检查,所以你你在前面,你先先把一个前置类的前置声明写上去,你告诉编译器哦,他在做编译器的类型,检查的时候呢,先提前知道,哦,这个是一个类来的,你按照类的类型检查,按照你这个你这个类型是一个类的类型,那编译器在做类的编译,在做例行检查的时候,从上到下,他要先提前知道,这个累啊,他后面就可以用了。否则的话,你从上到下执行你编译器做类型检查的时候,你不知道它是什么,可能它在后面才是明,所以你必须得提前在前面做一个前置声明,这样的话才能够让编译器做类型检查的时候,编译器类型检查的时候比较好。
这个主要还是西加加的编译器不够给力,他没有沉得住气,他不能把疑惑藏在心里,就是他如果有,有这种沉得住气,把疑惑藏在心里,他先看到了这个东西之后发现她在做参数,做编译器类型教育的时候,不认识的时候他先藏在心里,然后等到后面用,后面刷到了,从上到下运行代码,刷到这个类的时候,哦,他发现这是类这个生这个声明的这个东西是个累啊,然后他就知道了。但但C的编译器没有那么聪明,他沉不住气,他遇到了这个东西,他不知道的话,你,你如果你声明在后面,他沉不住气了,他不知道了,他他就就,就就觉得有问题,就是他不能把这个疑惑藏在心里,然后Java的话,他的编译器可能就聪明一点,他可以把这疑惑藏在心里,你不用前置声明,他如果遇到了这个东西,他没有,他前面还没有声明过,他就把这疑惑藏在心里,等到后面运行的时候。
然后等到后面运行时候遇到了这个这个类的声明之后,他说哦,原来这是个类呀,然后再把它给重新认识一下,然后这是个类Java的一个编译器,可能就有这么聪明,但C加加编译器沉不住气,它不能把这疑惑藏在心里,所以你要提前用个前置声明在前面给它,这样它显着。哦,这个这是一个类呀,后面它才能用,不然的话它沉不住气的,它这疑惑一旦出现了,它不会藏在心里。
他这个疑惑如果出现了,他不会藏在心里,等到后面知道了再去解决,他不知道就不知道。
他遇到这个问题不知道了,就卡住了,就直接报错了,就是卡住了,就说嗯,他不会这样,他不会像其他的玩比较聪明,他不会。
inline的进一步理解Line是怎么来的?你要理解这一点,你就必须要知道静态类型检查这个东西,它跟这东西是百分百挂钩的,阴赖本身就是一个宏定义的扩展宏定义,它跟阴赖区别是阴赖比宏定义多了一个进参数类型校验,就是这一点。
宏定义在设计的时候就是没有充分考虑到设计者跟使用者之间的沟通,你没有参数类型校验码那内参数你特别是代参宏,你怎么传我?万一传错了,你用不校验给我是吧?
所以,本质上inline函数就是宏定义的一个升级版。
你在Linux内核里面,你会看到很多只有写了一行的函数,那么,其实这个一行的函数调用开销是特别特别特别特别特别大的,但是为什么要这么写呢?它就是为了函数这样写出来,对程序员、程序员来讲比较看起来比较清晰。
是你清晰了,但是你从程序员的角度看清晰了,但是你从程序运行的角度来看,它效率越大,打折扣了,那么这时候就要依赖嘛,是依赖的出现,其实是有要有它的原因的。
In line跟类的结合会出现什么东西呢?这个在我们之前已经讲过了,就你如果在这类里面,你写了函数题,它默认就是in line的了,所以你可以把inline那个关键字给省略掉,它就是inline的,就是这样子。
它里面如果是空的,他也是一个依赖的,就比如如果你那个中括号里面是空的,就比如说你那个默认构造函数啊,特森然后一个一个括号,然后里面一个中括号里括号,然后后面是一个中括号,中括号里面是空的,他把他这个函数写成了一行,这其实也是内联函数来的啊,你知道吧,因为你他已经把函数实体写到类里面去了,你中括号在里里面你只写了一行的,然后这个的话,其实他也是依赖函数了哦,它只不过把依赖给省略掉了,因为你只要把函数体写到类里面去,那么他就是依赖函数,依赖函数它的依赖是可以省略掉的,实际上它本身是,所以他所以实际上它本身前面有依赖的,只不过把依赖这个关键字省略掉而已。
也就是说,你如果把函数体总结一点,就是你如果把函数体写到类里面,你的中括号写到类里面,那么这函数你就,它就会C加加,就处理时候就把它依赖化,把它进行online处理。
还有一种传统的方法,就是你在函数,你在类的外面类的,外面再写它那个方法的一个实题,在那里再写online。但是朱老师这里推荐什么呢?就推荐你如果真的要online了,那你就不用这么写了,不要按传统方法写了,你真的要online,那你就把函数实题写到类里面去就算了。
应该用不怕把类写得太长你不用怕把泪写的太长了,这个不用怕的。
朱老师,他个人认为,把泪写的长一点是没有太大关系的。
inline如果写外面,要写在下面这里还有一个注意的点,就是你如果真的要用传统方法把赖就是写到外面去嘛,用做传统方法的话,那么你这个online函数就不能写在CPP文件里面了吧,就不能写在那个第二个CPP文件里面了吧,就必须把这个online函数放到头文件里面去吧,就放到你的类的后面跟着。
这个为什么呢?因为C跟C加加的编辑器啊,它都是单个文件去编译的,然后链接的时候在链接在一起的,那你如果这样的话,你把inline函数写在了其他CPP文件里面去,那你这个时候是不是出现问题了?当我编译器在单个编译的CPP这个CPP文件的时候,你发现在依赖展开,不知道转到哪里去,是吧?它的原型是在那个,他的声明是在头文件APP里面,那你你在CP里面展开依赖,你没法展,你单个文件不知道哪里去,所以你必须得把它放到你那个APP里面去,把依赖那个函数放到APP里面去。
不然的话就会报错。



