Index:
(一) extern在C语言中作声明;
(二) static变量的作用域, C++中的静态成员;
(三) const关键字在函数重载中的作用.
(一)extern关键字
首先,声明与定义的区别:
定义:编译器会为变量或函数分配内存 //如:int a=1;
声明:只是表明其存在,但没有分配内存这个过程。//如:int a; 带或带extern
extern的两个作用:
(1)extern声明/定义变量和函数.
1.声明变量或函数, 例如extern int val; extern void fun (void);
在aaa.cpp 定义函数: void func();
在bbb.cpp 调用该函数前需要先extern声明: extern void func();
或者在aaa.h头文件里extern声明, 所有包含此头文件的*.cpp都可以是使用func()函数.
(2)当它与"C"一起连用时,例如:
extern "C" {
void fun(int a, int b);
} // 没有分号;
则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的, (原因是C++支持函数的重载,以及...)
使用代码示例:
#ifdef __cplusplus
extern "C" {
#endif
//...函数定义
#ifdef __cplusplus
}
#endif
(一) extern在C语言中作声明;
(二) static变量的作用域, C++中的静态成员;
(三) const关键字在函数重载中的作用.
(一)extern关键字
首先,声明与定义的区别:
定义:编译器会为变量或函数分配内存 //如:int a=1;
声明:只是表明其存在,但没有分配内存这个过程。//如:int a; 带或带extern
extern的两个作用:
(1)extern声明/定义变量和函数.
1.声明变量或函数, 例如extern int val; extern void fun (void);
在aaa.cpp 定义函数: void func();
在bbb.cpp 调用该函数前需要先extern声明: extern void func();
或者在aaa.h头文件里extern声明, 所有包含此头文件的*.cpp都可以是使用func()函数.
(2)当它与"C"一起连用时,例如:
extern "C" {
void fun(int a, int b);
} // 没有分号;
则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的, (原因是C++支持函数的重载,以及...)
使用代码示例:
#ifdef __cplusplus
extern "C" {
#endif
//...函数定义
#ifdef __cplusplus
}
#endif
http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html
(二)static关键字
1.static和extern不能同时修饰一个变量;
2.static修饰的全局变量声明与定义同时进行,比如static int val,此时变量val所占的内存已经被分配了.
3.static变量只在该文件内有效,如果.h文件中有定义static double price,那么每个include此h文件的模块都有一个单独的price变量,互不干扰.
4.static函数,如果static函数是类的成员,则此函数只能操作static成员.
5.c++中,类的static成员,不必实例化即可调用,比如Ctype::FuncName(),类的static数据成员,只占一份内存.
6.如果有如下的函数声明: static char func(void); 其中的static关键字不是修饰返回值char的, 而根据语境, 1修饰函数只在文件内有效, 2如果函数是类成员, 则表明这个函数可以在类没有实例化前而调用AClass::func();
在C/C++中, static变量都是存储在常量区, 生存周期都是一旦被创建, 一直存在.
在C语言中, static有了第二种含义:用来表示不能被其它文件访问的全局变量和函数.
在C+ +中, static还有第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数. 对于类的static成员, 该类的所有实例都共用一个static成员.比如在对某一个类的对象进行计数时, 计数生成多少个类的实例, 就可以用到静态数据成员. 注意, static成员函数必须只能调用static成员.
(三)const关键字
在C语言中, 常用#define MAX 1024这样的宏定义, 但是C++中不推荐这样做, 而采用const变量的方式定义一个常量.
1. 修饰常量/指针:
const int *p = &val; //p指向的类型是const int,指向的内容不能改变;
int const *p = &val; //同上
int * const p = &vala; //p指向的类型是int,指针本身的值不能改变;
const int * const p = &a;
2.const对象应该在定义时被赋值, const int* a = new int(0)[1024]; //ok
3.多文件中使用const变量:
extern const char g_str[]; //h文件声明
const char g_str[] = "123"; //c文件定义
4.函数中指针的const传递和返回:
const char* F2(); //意义是函数返回的指针指向的对象是一个const对象,它必须赋给一个同样是指向const对象的指针。
const char* const F3(); //比上面多了一个const,这个const的意义只是在他被用作左值时有效,它表明了这个指针除了指向const对象外,它本身也不能被修改,所以就不能当作左值来处理。
const char F2(); // 不修饰指针/引用的情况, 无意义, char c = F2() 不报错.
5.int Func() const; //函数Func()是类成员,表示此函数不能改变类对象,反之则编译器报错;
6.const在函数重载中的问题:
《C++ primer》中提到“仅当形参是引用或指针的时候,形参是否为const才对重载有影响。”
const重载情形(1):
int add(int a, int b);
int add(const int a, const int b); // 无意义的重载
在此的两个函数的形参并不会直接关联到实参,在调用这两个函数的时候,形参都只是实参的一个副本,不管add函数内部对 形参做什么处理,都不会影响到实参,也就是说——第二个函数形参中的const没有任何的用处,只是多此一举罢了。所以在此的第二个定义只是对第一个的重 定义罢了。
实参为非const对象的时候,其实两个版本函数都可以被调用,都与之匹配,因为非const对象不但可以初始化非const引用,也可以初 始化const引用。但由于非const对象初始化const引用的时候涉及到类型转换,所以此时带非const引用形参的函数为最佳匹配。
const重载情形(2):
int add(int &a, int &b);
int add(const int &a, const int &b);//可以重载
比如定义const常量x,y,代码中调用add(x,y)是第二个版本.
上述第2种情况:实参为const对象的时候,就不能将此对象传递给带非const引用的形参的函数了,因为const对象只能用来初始化const引用。
/*函数定义*/
int add(int *a, int *b);
int add(const int *a, const int *b);
int x = 1;
int y = 2;
const int r = 1;
const int s = 2;
add(&x, &y); //调用 add(int *, int *);
add(&r, &s); //调用 add(cosnt int *, cosnt int *);
C++是一个面向对象语言(虽不是纯粹的面向对象语言),它支持函数的重载,重载这个特性给我们带来了很大的便利。为了支持函数重载的这个特性,C++编译器实际上将下面这些重载函数:
void print(int i);
void print(char c);
void print(float f);
void print(char* s);
编译为:
_print_int
_print_char
_print_float
_pirnt_string
这样的函数名,来唯一标识每个函数。注:不同的编译器实现可能不一样,但是都是利用这种机制。所以当连接是调用print(3)时,它会去查找_print_int(3)这样的函数。下
C语言中并没有重载和类这些特性,故并不像C++那样print(int i),会被编译为_print_int,而是直接编译为_print等。因此如果直接在C++中调用C的函数会失败,因为连接是调用C中的print(3)时,它会去找_print_int(3)。因此extern "C"的作用就体现出来。
(二)static关键字
1.static和extern不能同时修饰一个变量;
2.static修饰的全局变量声明与定义同时进行,比如static int val,此时变量val所占的内存已经被分配了.
3.static变量只在该文件内有效,如果.h文件中有定义static double price,那么每个include此h文件的模块都有一个单独的price变量,互不干扰.
4.static函数,如果static函数是类的成员,则此函数只能操作static成员.
5.c++中,类的static成员,不必实例化即可调用,比如Ctype::FuncName(),类的static数据成员,只占一份内存.
6.如果有如下的函数声明: static char func(void); 其中的static关键字不是修饰返回值char的, 而根据语境, 1修饰函数只在文件内有效, 2如果函数是类成员, 则表明这个函数可以在类没有实例化前而调用AClass::func();
在C/C++中, static变量都是存储在常量区, 生存周期都是一旦被创建, 一直存在.
在C语言中, static有了第二种含义:用来表示不能被其它文件访问的全局变量和函数.
在C+ +中, static还有第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数. 对于类的static成员, 该类的所有实例都共用一个static成员.比如在对某一个类的对象进行计数时, 计数生成多少个类的实例, 就可以用到静态数据成员. 注意, static成员函数必须只能调用static成员.
(三)const关键字
在C语言中, 常用#define MAX 1024这样的宏定义, 但是C++中不推荐这样做, 而采用const变量的方式定义一个常量.
1. 修饰常量/指针:
const int *p = &val; //p指向的类型是const int,指向的内容不能改变;
int const *p = &val; //同上
int * const p = &vala; //p指向的类型是int,指针本身的值不能改变;
const int * const p = &a;
2.const对象应该在定义时被赋值, const int* a = new int(0)[1024]; //ok
3.多文件中使用const变量:
extern const char g_str[]; //h文件声明
const char g_str[] = "123"; //c文件定义
4.函数中指针的const传递和返回:
const char* F2(); //意义是函数返回的指针指向的对象是一个const对象,它必须赋给一个同样是指向const对象的指针。
const char* const F3(); //比上面多了一个const,这个const的意义只是在他被用作左值时有效,它表明了这个指针除了指向const对象外,它本身也不能被修改,所以就不能当作左值来处理。
const char F2(); // 不修饰指针/引用的情况, 无意义, char c = F2() 不报错.
5.int Func() const; //函数Func()是类成员,表示此函数不能改变类对象,反之则编译器报错;
6.const在函数重载中的问题:
《C++ primer》中提到“仅当形参是引用或指针的时候,形参是否为const才对重载有影响。”
const重载情形(1):
int add(int a, int b);
int add(const int a, const int b); // 无意义的重载
在此的两个函数的形参并不会直接关联到实参,在调用这两个函数的时候,形参都只是实参的一个副本,不管add函数内部对 形参做什么处理,都不会影响到实参,也就是说——第二个函数形参中的const没有任何的用处,只是多此一举罢了。所以在此的第二个定义只是对第一个的重 定义罢了。
实参为非const对象的时候,其实两个版本函数都可以被调用,都与之匹配,因为非const对象不但可以初始化非const引用,也可以初 始化const引用。但由于非const对象初始化const引用的时候涉及到类型转换,所以此时带非const引用形参的函数为最佳匹配。
const重载情形(2):
int add(int &a, int &b);
int add(const int &a, const int &b);//可以重载
比如定义const常量x,y,代码中调用add(x,y)是第二个版本.
上述第2种情况:实参为const对象的时候,就不能将此对象传递给带非const引用的形参的函数了,因为const对象只能用来初始化const引用。
/*函数定义*/
int add(int *a, int *b);
int add(const int *a, const int *b);
int x = 1;
int y = 2;
const int r = 1;
const int s = 2;
add(&x, &y); //调用 add(int *, int *);
add(&r, &s); //调用 add(cosnt int *, cosnt int *);