目录:
一、inline
二、类与对象基础
(一)类的定义
(二)访问限定符
(三)类域
(四)实例化概念
正文
一、inline
在C语言的学习过程中,大家肯定了解过宏这个概念。宏定义函数肯定也不陌生吧,它的优点是:灵活,程序运行速度快(代码少的情况下)、不用指定参数类型、不需要开辟空间。缺点是:大代码量频繁替换增加程序负担、运算符优先级会有冲突、不能调试。
针对以上宏函数的缺点就有了inline的出现,C++祖师爷创造出了inline来替代宏函数的使用。
用法:
(1)⽤inline修饰的函数叫做内联函数,内联函数不需要建⽴栈帧(也就是不用为函数开辟空间)可以提⾼程序效率,编译时C++编译器会在调⽤的地⽅展开(替换)内联函(此处和宏一样,在预编译阶段处理)
正常函数运行时会在堆栈开辟空间,若内联函数展开(替换)就不需要开辟空间
(2)inline对于编译器而言只是⼀个建议。inline适用于频繁调用的短小函数,代码相对多⼀些的函数加上inline也会被编译器忽略。
内联只是一个建议,你可以加但展不展开由编译器决定。编译时函数是会生成一条一条指令,一般当指令大于10条就不再展开函数。你可以想象一下:假设内联函数内有100条代码,如果编译器不干涉,要是调用1000次函数,重复的函数要展开(和宏替换一样)1000次每次100条指令,总程序代码长度为1000*100,运行起来将会很慢,所以编译器规定大于一定指令条数的内联函数不展开用栈帧为函数开辟空间调用。
栈帧开辟的函数空间不会因为你函数调用次数而改变原本大小。调用函数只执行一条代码就行,要是调用1000次函数,总程序代码长度为1000+100,相比内联函数快很多。
以下内联函数在编译时就不展开,忽略内联,Add函数将和普通函数一样在栈帧开辟空间。
(3)C语⾔实现宏函数也会在预处理时替换展开,但是宏函数实现很复杂很容易出错的,且不⽅便调试,C++设计了inline⽬的就是替代C的宏函数。
(4)为⽅便调试,vs编译器 debug版本下⾯默认运行是不展开inline的。debug版本想展开需要自行设置。
(5)inline不建议声明和定义分离到两个⽂件,分离会导致链接错误。
可理解为:定义一般在头文件内,程序运行时经过预处理,头文件会被展开,若内联函数符合编译器要求也会展开,而内联函数定义写在另一个文件,等执行到该语句编译器会认为在头文件已经展开过内联还函数了,此时不会再展开,而头文件展开的内联函数只是声明没有函数的有效地址,当调用该函数时无法找到地址就报链接错误。
错误写法:
正确写法:
【补充知识】正常函数定义不能写在头文件里
因为当头文件在不同文件中被包含多次,预编译时函数也会被展开多次,链接时就会生成多个函数,到时候调用不知道用哪一个会报冲突错误。解决办法是在头文件定义的函数前加static。因为static除了可以改变生命周期外还可以改变链接属性,让函数只能在该文件使用。
二、类与对象
(一)类的定义
(1)class为定义类的关键字,{}中为类的主体,注意类定义结束时后⾯分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的⽅法或者成员函数。
(2)为了区分成员变量,⼀般习惯上成员变量会加⼀个特殊标识,如成员变量前⾯或者后⾯加_ 或者 m开头,注意C++中这个并不是强制的,只是⼀些惯例,具体看公司的要求。
(3)C++中struct也可以定义类,C++兼容C中struct的⽤法,同时struct升级成了类,明显的变化是struct中可以定义函数,⼀般情况下我们还是推荐⽤class定义类。
C++类不再需要typedef,ListNodeCPP就可以代表类型
(4)定义在类中的成员函数默认为inline函数。
(二)访问限定符
(1)C++⼀种实现封装的⽅式,⽤类将对象的属性与⽅法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接⼝提供给外部的⽤⼾使⽤。
(2)public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private是⼀样的,以后继承章节才能体现出他们的区别。
例如:我给你提供了一个栈和一系列栈的函数,而你偏偏就自以为是觉得访问栈顶元素还要调用函数太麻烦,直接用右图方法,结果你不清楚我top并不是指向栈顶元素而是栈顶的下一个元素,你访问时没-1导致访问失败又反过来说我栈写的有问题。
以上错误就是C语言太自由导致的,所以C++祖师爷针对C语言做的一个优化创造出了类,你要访问我类里面的私有变量必须得通过我提供给你的类方法(函数)按我的规则去修改/访问,这样就不会出错。
(3)访问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后⾯没有访问限定符,作⽤域就到 }即类结束。(如下图)
(4)class定义成员没有被访问限定符修饰时默认为private,struct默认为public。这是两者间最明显的区别
也就是class类体中没有public,你什么也访问不了,而struct定义的类体中没有访问限定符,原本我不想让你访问的成员变量也可以被访问。
(5)⼀般成员变量都会被限制为private/protected,需要给别⼈使⽤的成员函数会放为public。成员变量是很重要的,一般不希望任何人能随意修改,必须调用类函数按规则修改。
(三)类域
(1)类定义了⼀个新的作⽤域,类的所有成员都在类的作⽤域中,在类体外定义成员时,需要使⽤ :: 作⽤域操作符指明成员属于哪个类域。
(2)类域影响的是编译的查找规则,下⾯程序中Init如果不指定类域Stack,那么编译器就把Init当成全局函数,那么编译时,找不到array等成员的声明/定义在哪⾥,就会报错。
指定类域Stack,就是知道Init是成员函数,当前域找不到的array等成员,就会到类域中查找。
(四)实例化概念
类就像一张图纸,你可以拿着这张图纸盖出多栋具体的房子。
如果类是一张图纸,那在它还没盖出实体房时,类是不占任何地面空间的。同理下图类的成员变量只是声明没有具体分配内存空间,类函数也是。
那么类成员什么时候才有具体的内存空间呢?
在拿这个类类型Date实例化对象d1和d2 的时候就自动分配内存空间(拿类类型实例化称为对象)
所以类真实存在有空间是实例化的时候(可理解为实实在在有空间叫实例化)
类与对象基础(上)加载完毕,有错别字或写不好的地方欢迎留言指出,必定虚心接受~
未完待续........