static关键字至少有下列n个作用:
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。
const关键字至少有下列n个作用:
(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。
C++类 虚函数 构造函数 析构函数相关
1)正确区分重载、重写和隐藏。
注意三个概念的适用范围:处在同一个类中的函数才会出现重载。处在父类和子类中的函数才会出现重写和隐藏。
重载:同一类中,函数名相同,但参数列表不同。
重写:父子类中,函数名相同,参数列表相同,且有virtual修饰。
隐藏:父子类中,函数名相同,参数列表相同,但没有virtual修饰;
或:函数名相同,参数列表不同,无论有无virtual修饰都是隐藏。
例如:
基类中:(1) virtual void show(); //是虚函数
(2) void show(int); //不是虚函数
子类中:(3) void show(); //是虚函数
(4) void show(int); //不是虚函数
1,2构成重载,3,4构成重载,1,3构成重写,2,4构成隐藏。另外2,3也会构成隐藏,子类对象无法访问基类的void show(int)成员方法,但是由于子类中4的存在导致了子类对象也可以直接调用void show(int)函数,不过此时调用的函数不在是基类中定义的void show(int)函数2,而是子类中的与3重载的4号函数。
2)不能为虚函数的是:静态函数,内联函数,构造函数
3)面向对象的三大基本特征:封装,继承,多态
封装是指把过程和数据包围起来,对数据的访问只能通过已定义的界面,可以隐藏实现细节,使得代码模块化;继承可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。多态:静态多态(函数重载,编译时绑定),动态多态(虚函数,运行时绑定)
每个类用了一个虚表,每个类的对象用了一个虚指针
A为基类,B为派生类
A *pa = &bB;编译器会隐式的执行派生类到基类的转换。
pa的结构就是A的布局(就是说用pa只能访问的到bB对象的前两项,访问不到第三项int b)
4)在类继承中,一般析构函数都要定义为虚函数
析构函数
执行当前的析构函数;重新解绑定虚函数表;调用基类析构函数
若base中析构函数不是虚函数:
Base* p = new A
delete p
这个过程只调用了Base的析构函数,没有调用A的析构函数。
这样在实际应用中会有不确定的后果,可能会memory leak
5)若没有提供,则合成default constructer的四种情况
带有default constructer的member class object
带有default constructer的base class
带有一个virtual Funtion的class
带有一个virtual Base class
6)在构造函数中需要初始化列表的三种情况
带有const修辞的类成员;
引用成员数据
需要初始化的数据成员是对象
指针数组和数组指针
指针数组:全部是指针的数组 char *p[16]
数组指针:指向数组的指针 char(*p)[16]
malloc_free函数和new delete区别
malloc是库函数,new是运算符
返回类型:new无需进行强制类型转换
内存分配失败的返回值:new只会抛出异常,malloc会返回NULL
是否需要指定内存大小
是否调用构造和析构函数
对数组的处理
是否可以互相调用
sizeof和strlen
sizeof运算符 strlen是函数
sizeof可用类型做参数,strlen只能是char*
编译时候sizeof就已经计算过 如char str[20]=”0123456789” sizeof(str)=20 strlen(str)=10
当变量为字符指针指向一个字符串,则sizeof(str)=4,和strlen的结果不一样
引用和指针的区别
1. 指针是一个实体,而引用仅是个别名;
2. 引用使用时无需解引用(*),指针需要解引用;
3. 引用只能在定义时被初始化一次,之后不可变;指针可变;
4. 引用不能为空,指针可以为空;
5. “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
typeid(T) == typeid(T&) 恒为真,sizeof(T) == sizeof(T&) 恒为真,但是当引用作为成员时,其占用空间与指针相同(没找到标准的规定)。
6. 指针和引用的自增(++)运算意义不一样;
代码运行的过程(预处理 编译 汇编 链接)
预处理:编译器对各种预处理命令进行处理,包括头文件的包含、宏定义的扩展、条件编译的选择等。
编译:对程序进行语法分析,并转换为汇编代码;
汇编:将汇编代码翻译为机器代码,生成目标文件;
链接:将目标文件和其他的文件合并在一起,得到最终的可执行文件。
动态链接和静态链接
静态链接库是.lib的格式,一般在工程的设置界面加入到工程中,程序编译时会把lib文件的代码加入到你的程序中,因此会增加代码大小,你的程序在运行时lib代码会一直在运行空间,不可以手动移除
动态链接库是程序运行时动态装入内存的模块,为.dll的格式,在程序运行时可以随意加载和移除,可以节约内存空间。
voilate(可能会被意想不到地改变),explicit关键字(来防止隐式转换)
内存分类 堆和栈的区别
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放(malloc/free, new/delete),若程序员不释放,程序结束后可能由操作系统回收。
3、全局区(静态存储区)(static)— 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。
堆区和栈区的区别主要分为
1、 管理方式 栈由OS来分配和释放,堆由用户自己
2、 空间大小 栈一般只有2M 堆一般比较大
3、 是否产生碎片
4、 生长方向 栈向下(内存地址减小的方向) 堆向上
5、 存取效率