1.static是C和C++中比较重要的关键字,某些情况下它在C和C++中的作用是相同的,首先讨论下它们作用相同的地方:
1)当static在C和C++中修饰函数中的局部变量时,编译器将改变它的存储形式,被修饰的变量和生命周期不会随着函数的退出而消亡。
2)当static在C和C++中修饰函数和全局变量时,可以简单的把它理解为private。下面写个简单的例子:
first.c:
#include <stdio.h>
int i;
void sayhello(){
i=10;
printf("In the first c file i=%d\n",i);
printf("Hello World!\n");
}
second.c
#include <stdio.h>
extern int i;
int main(){
i=20;
printf("In the main function i=%d\n",i);
sayhello();
return 0;
}
用gcc编译这两个文件: gcc first.c second.c 然后运行a.out ,结果为:
In the main function i=20
In the first c file i=10
Hello World!
如果你将first.c中的i和sayhello都声明为static之后,再编译,这个时候会报错:
second.c:(.text+0xb): undefined reference to `i'
second.c:(.text+0x15): undefined reference to `i'
second.c:(.text+0x2b): undefined reference to `sayhello'
私有化之后的变量和函数将不再可见,second.c中找不到它的定义。
2.在C++中static还有其特有的用法(主要体现在类变量和类函数中)
如果一个类中的某个成员或者函数用static修饰,那么此类成员和函数将被类和类的实例所共有。
person.h
#include <iostream>
#include <string>
using namespace std;
class person{
public:
static int id;
string name;
static void say();
person();
person(string name);
};
person.cpp
#include "person.h"
person::person(){}
person::person(string name):name(name){}
int person::id=10;
void person::say(){
cout<<"Hello everyone,Thank you for reading!"<<endl;
}
main.cpp
#include "person.h"
int main(){
person p;
person p1("caige");
person::say();
p.say();
p1.say();
cout<<"In person p,person id="<<p.id<<endl;
cout<<"In person p1:person id="<<p1.id<<endl;
cout<<"In person,id="<<person::id<<endl;
return 0;
}
用g++编译这两个文件: g++ person.cpp main.cpp 然后运行a.out ,结果为:
Hello everyone,Thank you for reading!
Hello everyone,Thank you for reading!
Hello everyone,Thank you for reading!
In person p,person id=10
In person p1:person id=10
In person,id=10
在这里需要注意的是static修饰的类成员和函数的初始化。对于person中的id,其只能在定义的时候初始化,并且不能在类中初始化。
如果在person.h中把static int id; 更改为satic int id=10;则会报错(如果改为const static int id=10则不会报错):
In file included from person.cpp:1:0:
person.h:8:23: 错误:ISO C++ 不允许在类内初始化非常量静态成员‘id’
In file included from main.cpp:1:0:
person.h:8:23: 错误:ISO C++ 不允许在类内初始化非常量静态成员‘id’
另外在person.cpp中初始化id变量和say()函数时,其前面一定不能加static,虽然在类中声明的时候其前面都有sattic。其报错信息如下:
person.cpp:6:20: 错误:与声明不同,定义静态数据成员时不能使用‘static’ [-fpermissive]
person.cpp:8:25: 错误:不能将成员函数‘static void person::say()’声明为有静态链接 [-fpermissive]
satic还可以用来把一个class声明为内部存储类,在这里不多作说明!!!
3.关于不同源文件中成员和函数的互相访问的比较
这个标题有点绕口,如果您有耐心读到这里并且读完,我相信您一定不会后悔的!
用上面写的两个c源文件first.c和second.c来举例说明,在first.c中我声明了sayhello()函数,在second.c中我并没有写extern void sayhello(),
但是它却可以正常的调用first.c中的sayhello()函数。在C++中如果没有extern void sayhello();这条语句是会报错的!!!报错信息:
second.c: 在函数‘int main()’中:
second.c:8:11: 错误:‘sayhello’在此作用域中尚未声明
C++的编译器压根就不知道sayhello()是什么玩意儿。
另外,如果一个C++源文件要引用另一个C++源文件中的类(非satic),则必须在此源文件中复制类的所有声明,不需复制实现!用上面的例子说明:
将上面的person.cpp和main.cpp改成下面这样:
改版person.cpp
#include <iostream>
#include <string>
using namespace std;
class person{
public:
static int id;
string name;
static void say();
person();
person(string name);
};
person::person(){}
person::person(string name):name(name){}
int person::id=10;
void person::say(){
cout<<"Hello everyone,Thank you for reading!"<<endl;
}
改版main.cpp
#include <iostream>
#include <string>
using namespace std;
class person{
public:
static int id;
string name;
static void say();
person();
person(string name);
};
int main(){
person p;
person p1("caige");
person::say();
p.say();
p1.say();
cout<<"In person p,person id="<<p.id<<endl;
cout<<"In person p1:person id="<<p1.id<<endl;
cout<<"In person,id="<<person::id<<endl;
return 0;
}
用g++编译这两个源文件: g++ person.cpp main.cpp,结果为:
Hello everyone,Thank you for reading!
Hello everyone,Thank you for reading!
Hello everyone,Thank you for reading!
In person p,person id=10
In person p1:person id=10
In person,id=10
注意main.cpp中只是copy了person.cpp中关于person的定义,而没有copy其实现。但是其能正常的编译和运行。(没有用person.h)
C和C++源文件中互相访问各自的函数是有差别的,C中可以省略extern语句,C++不能省略。为了养成一个良好的编程习惯,写代码
的时候还是尽量把extern语句加上。要始终记住:所有编程语言中的变量和函数都必须是先定义后使用!
11月20日新增:
C和C++中关于strcut中的一点小小差别:
#include <stdio.h>
struct person{
int name;
int id;
};
int main(){
typedef struct person person;
person p;
printf("%d\n",p.name);
}
#include <iostream>
struct person{
int name;
int id;
};
int main(){
person p;
std::cout<<p.name<<std::endl;
return 0;
}
在第一段代码中如果没有typedef struct person person;这条语句,编译的时候将会报错!而C++中则没有如此严格的要求!