1,extern
1,在文件1中有一个全局变量A(也就是在所有的函数体之外),当在文件2中直接使用这个变量时,就会找不到,
但是,如果在文间中写出文件1中全局变量A的声明,并在声明前加上extern,就可以使用。
总结来说,这个关键字解决了用户想使用其他文件中的全局变量或者函数,又不想包含这个文件的问题。
如果一个全局变量被声明为static,那么即使使用extern也无济于事。
2, 文件1中的函数 Func( ) ,在文件2中被声明为extern,则在 文件2中也可调用这个函数。
2,static
面向过程(C语言):
1, static修饰全局变量,全局变量存储在全局区,作用域是整个文件中,这时即使在其他文件中使用extern也不能问。
生命周期随进程的结束而结束。
2, static修饰局部变量,这时局部变量存储在全局区,但作用域是函数或者定义的语句内,当语句或者函数结束时,
静态局部变量不销毁,重复调用语句和函数时,变量的值还是以前的值,也就是说生命周期延长了。
3, static修饰函数时,这个函数的作用域是本文件内,这时即使在其他文件中使用extern修饰也不能访问。
面向对象 (C++):
1,static修饰类中普通成员变量,那么这个成员变量就变成了静态成员变量,静态成员变量属于类中,
而不属于某个对象,所以调用静态成员变量,可以直接通过类名,也可以通过对象名,
也就是说,静态成员变量在一开始只分配一次内存,所有对象都可以共享。
2,与全局变量相比,静态成员变量的优点是
1,静态成员变量没有的作用域是类中,没有进入全局命名空间,不存在与其他全局名字冲突的可能性。
2,静态成员变量可以使用private进行隐藏,但是全局变量不行。
3,static修饰类中普通成员函数,则变成静态成员函数,和静态成员变量一样,属于类中,而不属于某个对象。
是所有对象共享的,所以调用静态成员函数,可以直接通过类名,也可以通过对象名。
静态成员函数不与任何对象发生联系,所以不具有this指针,所以它无法访问普通成员函数和变量。
只能调用静态成员函数和变量。
总结:
0,static成员变量必须在类外定义,就是因为它是属于类的,定义在类中会被所有对象拥有。
但是const static成员变量可以在类中定义,因为这个static变量不会被改变。
不同对象的const static成员地址一样,即是同一个变量。
1,出现在类体外的函数定义不能指定关键字static,static函数可以在 类外定义。
,2, 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
3,非静态成员函数可以任意地访问静态成员函数和静态数据成员;
4,静态成员函数不能访问非静态成员函数和非静态数据成员;
5,由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
6,调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,
也可以直接使用如下格式:<类名>::<静态成员函数名>(<参数表>)调用类的静态成员函数。
3,volatile
防止编译器对代码进行优化,防止编译器对某个变量直接从寄存器中读取,而忽略 内存,保证内存的可读性。
提醒编译器这个变量随时 会变化 。
简单来说就是,由于编译器的优化会改变程序员的初衷,造成很多坑,volatile就是来填这个坑的。
4,inline
概念:用inline修饰的函数叫做内联函数,在调用内敛函数时不会开辟新的函数栈帧,
而是在调用位置 将函数展开,顺序执行。
特点:1,内敛函数放弃函数栈帧,选择增加函数长度,这是以空间换时间的做法,
所以函数长度大,内部循环复杂的函数不宜定义为内敛函数,构造函数和析构函数也不宜,
因为,派生类构造与析构函数往往还包含着基类的构造 与析构函数。
2,inline对于编译器来说只是 一个建议,编译器会对函数检查选择,如果有大量循环与递归的话,
编译器就会忽略。
3, inline必须放在函数的定义处,而不是函数的声明处,这是因为内敛函数的展开是在编译阶段完成,
若只是在声明处使用inline则不起任何作用。
4,定义在类内的成员函数默认是内联函数,所以最好将构造和析构函数定义在类外。
相关面试题:
1,内联函数与宏函数的比较。
1,宏函数的展开是在预编译阶段,由预编译器完成,没有任何的函数栈帧行为,只是纯文本替换。
内联函数的展开是在编译阶段,由编译器完成,存在函数栈帧行为(参数压栈等)。
2,宏函数不存在参数类型的检查,不可调试,不可存取私有数据,不可以作为类成员函数。
内联函数会有类型检查,可以调试,可以存取私有数据,可以作为 类成员函数。
2,总结:在C++中强烈建议使用const 替换宏常量,使用内联函数替换宏函数。
5,explicit
首先分享一个关于ecplicit讲的不错的博客 https://blog.csdn.net/breaksoftware/article/details/54894444
expilit关键字主要是防止构造函数的隐式类型转换。
简单来说就是,就是形参为类类型,实参是类对象时可以,实参为该类的单参构造函数的参数也可以,
但是这样的方法会出现很多人为差错,所以不建议使用,解决的方法就是在构造函数前加上ecplicit关键字。
来拒绝构造函数隐式的类型转换。
6,mutable
用途:用 mutable 修饰的成员变量在任何时间和地点都可修改,即使变量用const修饰。
主要是用来突破const的封锁。
7,const
用途:用const修饰一个变量表示这个变量一直是可变的。
1,const修饰形参,一般和引用同时使用 ,
2,const修饰返回值 const修饰类数据成员,必须在构造函数的初始化列表中初始化
3,const修饰类成员函数,实际修饰隐含的this,表示在类中不可以对 类的任何成员进行修改,
4,在const修饰的成员函数中要对类的某个数据成员进行修改,该数据 成员定义声明是必须加mutable关键字
常见的问题:
1. const对象可以调用非const成员函数和const成员函数吗?
不可以
2. 非const对象可以调用非const成员函数和const成员函数吗?
可以
3. const成员函数内可以调用其它的const成员函数和非const成员 函数吗?
可以电调用从const函数,不可以调用非const函数。
4. 非const成员函数内可以调用其它的const成员函数和非const成 员函数吗?
都可以