浅析extern、static、const
2016-06-17 17:14
211 查看
extern
C和C++中用extern关键字修饰变量或函数,说明该变量或函数是全局性的。extern声明的外部变量和函数告诉编译器,该变量和函数的声明和定义不在同一文件中,而要在其他文件中查找定义。
变量在被extern声明时并不对其分配有效空间,而是在定义时分配空间。
extern与“C”连用
这是在C++中的使用方法,比如:extern "C"+函数声明,则告诉编译器按照C语言的函数命名规则去编译后面的函数,而不是C++的函数命名规则。其实C语言与C++的函数命名规则是不一样的。
static
static关键字是C,C++共有的。 被static修饰的变量(函数)具有了静态属性,称他们为静态变量(函数)。具体用法有三种:
1.用static声明静态局部变量。
2.用static声明静态外部变量或函数。
3.用static声明静态数据成员或成员函数。
其中第三点是C++中所特有的,因为C语言中没有类的概念也就没有数据成员和成员函数。
一、静态局部变量
在函数内部用static声明的变量为静态局部变量,普通类型的变量是被分配到栈中存储,而静态类型的变量是被分配到静态区存储。被分配到静态区的变量在函数调用结束后,它的值和存储单元不被系统自动释放而是保留原值,在下一次函数调用时保留上次函数调用后的值。等改程序执行完后再由系统清除。
1.静态局部变量在静态存储区内分配存储单元。
2.对静态局部变量是在编译时赋初值的,即只赋初值一次,在程序运行时它已有初值。
3.在定义静态局部变量时如果没有赋初值,则系统给该变量默认赋值为0。
4.声明在本函数内部的静态局部变量不可以被其他函数调用。
二、静态外部变量
在函数外部用static修饰的变量或者函数它的作用域被限制在本文件范围内,不能被其他文件调用。此时的静态变量或函数并不是采用静态存储方式(分配在静态存储区),而是他们的作用域被限制在本文件。无论外部变量是否有static修饰,它都是被存储在静态区中。
静态数据成员和静态成员函数是C++所特有的性质,静态数据成员是各对象所共有的,对象中数据成员的值是一样的,是属于类的,所有对象都可以应用它。静态数据成员在内存中只占用一份空间,如果改变它的值,则在各对象中这个数据成员的值都会同时改变。这样就节省了空间,提高运行效率。
总结
1、静态成员为所有类对象所共享,不属于某个具体的实例。
2、类静态成员即可用类名::静态成员或者对象.静态成员来访问
3、类静态成员变量必须在类外定义,定义时不添加static关键字
4、类的静态成员函数没有默认的this指针,因此在它里面不能使用任何非静态成员
5、静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值,const修饰符等参数。
注意
1.静态成员函数不能访问非静态成员(数据、函数),只能访问静态成员(数据、函数)。
2.非静态成员函数可以访问静态成员(数据、函数)。
const
被const修饰的变量是不能够修改的。const int a=10,在C语言中a是一个不可修改的常量,而在C++中a是一个常量,在C++中利用const常量取代了C语言中的宏定义。需要特别注意的是,被const修饰的变量在声明的时候必须初始化。
一、const常量和define
在C语言中要想使用一个常量通常会在文件头利用define来定义,但这种方法在C++中认为是不好,不安全的。C++中利用const常量来取代它。二者的优缺点对比如下:
C语言中的宏:
1.不进行类型检测。
2.不能调试.
3.容易造成代码膨胀,降低效率。
而C++中的const常量是可调试,并进行类型检测的。
二、const指针
const修指针有两种用法,一种是修饰指针指向的对象,一种是修饰指针的本身。在这里通过一种简单的方法来进行区分,将指针类型隐藏,然后看const关键字右边的第一个字符。如果是指针变量,则说明const修饰的是指针变量本身,如果是*,则说明的修饰的是指针变量指向的对象。
三、const函数参数
将函数参数声明为const,说明使用这种参数是为了提高程序执行效率和提高安全性,这样函数在调用该对象时,在函数内部就不能对对象的值进行修改。同理,将指针参数声明为const,函数将不修改由这个参数所指的对象。
可以阻止用户修改返回值。格式如下:
const int Test();
五、const修饰类成员
const修饰类成员是C++中所特有的性质,这里包括类数据成员、类对象和类成员函数。
1.被const修饰的数据成员,必须在构造函数的初始化列表中初始化。
类名 const 对象名[(实参表)];
或者
const 类名 对象名[(实参表)];
注意
常对象只能调用常成员函数,不能调用普通成员函数。而非const对象既可以调用普通成员函数,也可以调用常成员函数。
3.普通的成员函数可以调用本类中的非const成员,并可以在函数中修改它们。如果将成员函数声明为常成员函数,则只能引用本类中的数据成员,而不能修改它们。
1.常成员函数的声明和定义时都要在括号的最后边加const关键字。
2.常成员函数只能调用const成员函数,不能调用非const成员函数。
3.非const成员函数内可以调用其它的const成员函数和非const成员函数。
总结
C和C++中用extern关键字修饰变量或函数,说明该变量或函数是全局性的。extern声明的外部变量和函数告诉编译器,该变量和函数的声明和定义不在同一文件中,而要在其他文件中查找定义。
变量在被extern声明时并不对其分配有效空间,而是在定义时分配空间。
extern与“C”连用
这是在C++中的使用方法,比如:extern "C"+函数声明,则告诉编译器按照C语言的函数命名规则去编译后面的函数,而不是C++的函数命名规则。其实C语言与C++的函数命名规则是不一样的。
static
static关键字是C,C++共有的。 被static修饰的变量(函数)具有了静态属性,称他们为静态变量(函数)。具体用法有三种:
1.用static声明静态局部变量。
2.用static声明静态外部变量或函数。
3.用static声明静态数据成员或成员函数。
其中第三点是C++中所特有的,因为C语言中没有类的概念也就没有数据成员和成员函数。
一、静态局部变量
在函数内部用static声明的变量为静态局部变量,普通类型的变量是被分配到栈中存储,而静态类型的变量是被分配到静态区存储。被分配到静态区的变量在函数调用结束后,它的值和存储单元不被系统自动释放而是保留原值,在下一次函数调用时保留上次函数调用后的值。等改程序执行完后再由系统清除。
int Test() { static int c = 1; c++; return c; } int main() { printf("%d\n", Test()); printf("%d\n", Test()); //每次调用完成后值保留 system("pause"); return 0; }总结
1.静态局部变量在静态存储区内分配存储单元。
2.对静态局部变量是在编译时赋初值的,即只赋初值一次,在程序运行时它已有初值。
3.在定义静态局部变量时如果没有赋初值,则系统给该变量默认赋值为0。
4.声明在本函数内部的静态局部变量不可以被其他函数调用。
二、静态外部变量
在函数外部用static修饰的变量或者函数它的作用域被限制在本文件范围内,不能被其他文件调用。此时的静态变量或函数并不是采用静态存储方式(分配在静态存储区),而是他们的作用域被限制在本文件。无论外部变量是否有static修饰,它都是被存储在静态区中。
//file1.cpp static int a=1; static void Test() { } int main() { } //file2.cpp extern int a; //错误,无法使用file1.cpp中定义的static变量 extern void Test(); //错误,无法使用file1.cpp中定义的static函数三、静态数据成员、静态成员函数
静态数据成员和静态成员函数是C++所特有的性质,静态数据成员是各对象所共有的,对象中数据成员的值是一样的,是属于类的,所有对象都可以应用它。静态数据成员在内存中只占用一份空间,如果改变它的值,则在各对象中这个数据成员的值都会同时改变。这样就节省了空间,提高运行效率。
总结
1、静态成员为所有类对象所共享,不属于某个具体的实例。
2、类静态成员即可用类名::静态成员或者对象.静态成员来访问
3、类静态成员变量必须在类外定义,定义时不添加static关键字
4、类的静态成员函数没有默认的this指针,因此在它里面不能使用任何非静态成员
5、静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值,const修饰符等参数。
注意
1.静态成员函数不能访问非静态成员(数据、函数),只能访问静态成员(数据、函数)。
2.非静态成员函数可以访问静态成员(数据、函数)。
const
被const修饰的变量是不能够修改的。const int a=10,在C语言中a是一个不可修改的常量,而在C++中a是一个常量,在C++中利用const常量取代了C语言中的宏定义。需要特别注意的是,被const修饰的变量在声明的时候必须初始化。
一、const常量和define
在C语言中要想使用一个常量通常会在文件头利用define来定义,但这种方法在C++中认为是不好,不安全的。C++中利用const常量来取代它。二者的优缺点对比如下:
C语言中的宏:
1.不进行类型检测。
2.不能调试.
3.容易造成代码膨胀,降低效率。
而C++中的const常量是可调试,并进行类型检测的。
二、const指针
const修指针有两种用法,一种是修饰指针指向的对象,一种是修饰指针的本身。在这里通过一种简单的方法来进行区分,将指针类型隐藏,然后看const关键字右边的第一个字符。如果是指针变量,则说明const修饰的是指针变量本身,如果是*,则说明的修饰的是指针变量指向的对象。
const int *p1; //const修饰指针p1指向的对象,p1可变,p1指向的对象不可变 int const *p2; //同上 int* const p3; //const修饰指针p3,p3不可变,p3指向的对象可变 const int* const p4; //同上例子中第一条语句和第二条语句属于同一类型,第三条和第四条语句属于同一类型。
三、const函数参数
将函数参数声明为const,说明使用这种参数是为了提高程序执行效率和提高安全性,这样函数在调用该对象时,在函数内部就不能对对象的值进行修改。同理,将指针参数声明为const,函数将不修改由这个参数所指的对象。
void Test1(const int a); //函数不能修改变量a void Test2(const char* b); //函数不能修改指针b指向的变量四、const修饰函数返回值
可以阻止用户修改返回值。格式如下:
const int Test();
五、const修饰类成员
const修饰类成员是C++中所特有的性质,这里包括类数据成员、类对象和类成员函数。
1.被const修饰的数据成员,必须在构造函数的初始化列表中初始化。
class A { public: A(int b = 0) :_a(0) //必须在初始化列表中初始化 { _b = b; } const int _a; private: int _b; };2.被const修饰的类对象为常对象,同样常对象在定义的时候必须要有初值。在常对象的生命周期中,它的数据成员的值都是不能被修改的。
A const a1(1); //定义常对象a1定义常对象的一般格式:
类名 const 对象名[(实参表)];
或者
const 类名 对象名[(实参表)];
注意
常对象只能调用常成员函数,不能调用普通成员函数。而非const对象既可以调用普通成员函数,也可以调用常成员函数。
3.普通的成员函数可以调用本类中的非const成员,并可以在函数中修改它们。如果将成员函数声明为常成员函数,则只能引用本类中的数据成员,而不能修改它们。
void Display()const; //const在函数名和括号的最后边注意
1.常成员函数的声明和定义时都要在括号的最后边加const关键字。
2.常成员函数只能调用const成员函数,不能调用非const成员函数。
3.非const成员函数内可以调用其它的const成员函数和非const成员函数。
总结
数据成员 | 非const的普通成员函数 | const成员函数 |
非const的普通数据成员 | 可以引用,可以改变值 | 可以引用,不可以改变值 |
const数据成员 | 可以引用,不可以改变值 | 可以引用,不可以改变值 |
const对象 | 不可以引用 | 可以引用,不可以改变值 |
相关文章推荐
- 使用命令修改注册表键值及权限
- mysql的分区表
- java基础-容器
- IOS ReactiveCocoa 和 MVVM 入门
- 解决RecyclerView 使用 gridlayoutmanager 时item不居中问题
- 实现单实例应用程序的三种方法
- quartz在web项目中的应用(不使用spring)
- 关于ubuntu中利用crontab设置定时任务的问题
- Navicat for mysql 显示中文乱码问题
- ios学习--ios中的网络加密初探
- HDU 1874 畅通工程续 (SPFA)
- AsyncTask
- Ansj中文分词说明
- 四大常用排序算法实现-JAVA版
- 图像处理之图像特征提取之(二)LBP特征
- GetThreadContext找到程序占用CPU的技巧
- oracle 新建表空间 新建库 新建用户
- 实验补做
- DPDK杂记
- 深入理解 KVC\KVO 实现机制 — KVC