c++ 中的static 和 extern.docx
- 文档编号:9350883
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:12
- 大小:18.03KB
c++ 中的static 和 extern.docx
《c++ 中的static 和 extern.docx》由会员分享,可在线阅读,更多相关《c++ 中的static 和 extern.docx(12页珍藏版)》请在冰豆网上搜索。
c++中的static和extern
static在C/C++中有两层含义:
(1)表示静态存储,在一个称之为静态数据区的内存空间上存储对象,而不是象一般对象在调用函数产生的堆栈上存储,这使得静态对象比一般对象拥有更长的生命期(从该对象定义处一直到程序结束)。
(2)控制(对象或者函数)名字的可见性,被static修饰的成员仅有文件作用域和类作用域,在其他单元内是不可见的,就是说通过extern限定的变量是不可以引用被声明为static变量的。
1:
关于静态存储
1:
在函数内部定义静态变量(内部数据类型)
voidfun(){
staticinti=0;//static变量
i++;
intm=0;
m++;
cout<<"statici:
"<
cout<<"localm:
"< } intmain(){ fun(); fun(); } 程序运行输出结果: statici: 1 localm: 1 statici: 2 localm: 1 这样的结果很好理解,静态变量在函数调用结束的时候不会被收回,而且仅在第一次调用函数的时候初始化。 对于内部类型(int,char……)如果在声明的时候没有定义初值,系统会自动赋0值 2: 在函数内部定义静态对象 对于静态对象,如果在声明的时候没有赋初值,那系统只能调用其缺省的构造函数,如果类不能调用缺省构造(私有构造),则必须自行初始化,看下面程序 classobj{ public: obj(){ cout<<"obj: : obj()"< } obj(inti){ cout<<"obj: : obj(inti=0)"< } ~obj(){ cout<<"obj: : ~obj()"< } }; voidfun(){ staticobjx;//obj类必须有缺省构造函数 staticobjx2 (1);//可以初始化该对象 } intmain(){ fun(); fun(); } 输出结果: obj: : obj() obj: : obj(inti=0) obj: : ~obj() obj: : ~obj() 在函数一共调用了两次fun,但是x和x2仅进行了一次初始化。 3: 类中的静态数据成员 类的静态数据成员代表了该类的所有对象实例只使用一个共用的静态变量,无论这个类产生了多少对象,看下面的程序和输出的内容: classobj{ public: obj(char*str){ cout< obj();size: "< } voidset(inti=0){ if(i! =0){ size=i; } } voidprint()const{ cout<<"size: "< } private: staticintsize; }; intobj: : size=100;//必须用这样的方式初始化 voidfun(){ objx1("x1"); x1.print(); x1.set(200); x1.print(); objx2("x2"); x2.set(300); x2.print(); x1.print(); } intmain(){ fun(); } 输出结果: x1: obj();size: 100 size: 100 size: 200 x2: obj();size: 200 size: 300 size: 300 看输出的内容很快就会明白,x1和x2使用的是同一个size 3: 类中静态常量和静态数组 明白了类中静态变量的意思那静态常量已经静态常量数组就很快能明白,只是他们的初始化方式有些不同之处,看下面的代码: classMe{ staticintm_length; staticconstintsize=100;//仅内部类型可以在类内部定义静态常量 staticconstintnumber; staticintm_tips[]; staticconstintarray[]; }; //初始化静态成员 //必须为所有类静态对象提供外部定义,包括静态数组和静态常量数组 //由于是默认内部编译联接,可以在头文件中提供这些定义 intMe: : m_length=99; constintMe: : number=200; intMe: : m_tips[]={1,2,3,4,5}; constintarray[]={1,2,3,4,5}; 对于嵌套类可以有静态成员,定义方式仅需要额外的加上类限定符就可以了,函数内部的局部类不可以有静态成员。 4: 类中静态成员函数 类的静态成员函数和静态数据成员类似,它服务于类的全体对象。 静态成员函数由于没有接收当前对象的地址(this),它就无法访问一般的非静态成员,也就是说,static成员函数只能使用静态数据成员和静态成员函数,关于静态成员函数和类成员的关系看下面的代码: classXX{ public: XX(intm=0): i(m){ add(); j=i; j++; //普通成员函数可以调用静态函数和成员 } intfun(){ j++; returni=j; } staticintadd(){ returnj++; //i++;不可以这样作,理由是静态成员函数仅能访问静态数据 } staticintget(){ //fun();不可以这样作,理由是静态成员函数仅能访问静态数据 returnadd(); } private: inti; staticintj; }; intXX: : j=0; intmain(){ XXx; XX*px=&x; //静态成员函数调用方式,意义相同 x.add(); px->add(); XX: : add(); } 2: 关于static和extern控制名字访问 一般情况下在定义文件中(一般是cpp文件)定义的所有的名字是外部连接的,对于连接器该名字是可以见的,在另外的定义文件中用extern关键字可以访问这样的名字,全局变量和普通变量还有函数都可以有外部连接。 但是用static修饰的对象或者函数的名字,仅有单文件作用域,在其他文件中不可以被链接,可以说static修饰的名字仅在该名字出现的文件内可用。 见下面的代码 //文件main.cpp #include usingnamespacestd; intmain(){ externintxsize;//此处用extern指定xsize在别的地方定义 cout<<"xsize: "< } //文件test.cpp intxsize=5;//或者可以这样做 externintxsize=5; 而如果上面在test.cpp文件中声明xsize为static,在main.cpp中就不能使用该xsize了,程序如下; //文件main.cpp #include usingnamespacestd; intmain(){ externintxsize; //cout<<"xsize: "< } //文件test.cpp staticintxsize=5;//文件内部作用域,别处不可见 仔细对比一下不难发现他们的差别,static声明的名字不可以用extern访问,这样可以有一个好处就是确保连接时不会发生名字冲突,如果想在文件作用域中定义一个自己用的全局变量,那最好使用static声明。 3: 关于extern声明对象为外部连接的初始化问题 用extern声明的对象在该对象被使用之前必须已经被初始化,如果不是这样程序就会发生错误。 见下面的代码 //a.cpp #include std: : ofstreamout("outff"); //b.cpp #include externstd: : ofstreamout; classOfile{ public: Ofile(){out<<"file"< : endl;} }ofile; 在b.cpp中定义的对象初始化取决于a.cpp中的out是否已经被初始化,如果初始化顺序颠倒,系统就会出现错误。 咱们再来看大师们作品中提到的例子《TheAnnotatedc++ReferenceManual》 //a.cpp externinty; intx=y+1; //b.cpp externintx; inty=x+1; 在不同的文件中,x,y的值取决于文件被初始化的顺序,由于上面定义的是内部类型,编译器可以在上述情况下确保一个变量初始化为零。 如果a.cpp先被初始化则: y先被初始化为0,x=1;b.cpp后y=2 如果b.cpp先被初始化 x先被初始化为0,y=1;a.cpp后x=2; 看着这样的运行结果很是让人郁闷,真不知道为什么要有这样的特性。 其实编程语言特性愈多就越能体现它的灵活,但是这样的语言写出的代码可读性却降低了。 可能程序在一个编译器下编译出的程序运行正常,但是另外一个编译器编译出的东西就会让你大为郁闷。 对于上面的问题我们可以有两种方法解决。 这两个技术都在《thinkinginc++》中有详细的阐述。 我在copy一下就可能会侵犯版权了J而且也说得并不是很详细,大家还是去买本书来瞧瞧来的实在些。 4: 关于extern“C” 在C++中写程序有时会用到用C写的库程序,这时候就需要用到extern“C”,这就是所谓的“替代连接”,出现这样的情况是由于C编译的函数的隐式调用方式与C++调用函数的方式是不相同的,利用下面的语句声明表示在C++中想进行C方式的连接类型 //单个函数替代连接 extern"C"floatfun(inta,intb); //表示连接已经定义过并用C编译过的函数 //一组函数替代连接 extern"C"{ floatfun1(inta,intb); floatfun2(intx,inty); //....otherfunctions } //将另外头文件中函数进行替代连接 extern"C"{ #include"header.h" //...other.hfiles } 基本替换方式就上面的几种,在很多情况下,C++编译器设计者或者库的设计者已经预先进行了上述的处理。 本文来自CSDN博客,转载请标明出处:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- c+ 中的static extern 中的 static