C++中static关键字在类中常见问题分析

来源:互联网 发布:ios性能优化 yytext 编辑:程序博客网 时间:2024/06/06 13:58

一.static变量的初始化问题

static变量是和类绑定的变量,和一般变量和对象绑定不同。它在类实例化(创建对象)之前就分配空间,而非static变量是在创建对象时进行空间分配。那么该在哪里对static变量进行初始化呢?

1.能否在构造函数里进行static变量的初始化?
由前面的叙述可知,static变量在对象创建前就要进行空间分配。而构造函数是在创建对象时进行的调用。因此,不能在构造函数中对static变量进行初始化。
有如下代码:
#include "iostream"using namespace std;class test{public:static int a;test(){a=10;cout<<"a is "<<a<<endl;}};int main(void){test a;}
用g++进行编译,显示:

test.cpp:(.text._ZN4testC2Ev[_ZN4testC5Ev]+0xf):对‘test::a’未定义的引用

test.cpp:(.text._ZN4testC2Ev[_ZN4testC5Ev]+0x19):对‘test::a’未定义的引用

collect2: error: ld returned 1 exit status


2.能否在类中对static变量初始化?

有如下代码:

#include "iostream"using namespace std;class test{public:static int a;test():a(10){cout<<"a is "<<a<<endl;}};int main(void){test a;}

用g++进行编译,显示:

error: ISO C++ forbids in-class initialization of non-const static member ‘test::a’

C++标准中禁止对非const的static变量进行类内初始化。

也就是说如果将类中的

static int a;

改为:
const static int a;
便可以正常进行编译链接。

3.正确的初始化方式
#include "iostream"using namespace std;class test{public:static int a;test(){cout<<"a is "<<a<<endl;}};int test::a=10;int main(void){test a;}
类中的静态变量应该在类外进行初始化。

二.static成员与非static成员之间的调用

1.对static函数与非static函数的调用方式

1)通过类名的调用:因为static函数是与类绑定的,不依赖于对象,可以通过(类名::函数名)的方式来调用static函数。而非static函数则不能这样调用。
2)通过对象的调用:static函数和非static函数都可以通过(对象.函数名)的方式来调用。

2.static函数对类中其它成员变量的调用

有如下代码:
#include "iostream"using namespace std;class test{public:static int a;int b;test():b(10){}static void s_display(){cout<<"This is static display: a="<<a<<" b="<<b<<endl;}void display(){cout<<"This is non-static display: a="<<a<<" b="<<b<<endl;}};int test::a=10;int main(void){test a;a.s_display();a.display();return 0;}

用g++进行编译,提示:
error: invalid use of member ‘test::b’ in static member function
错误:在静态成员函数中错误的使用了(非静态)成员b。

但是并没有对static函数中对static变量的调用报告错误。也就是说,可以在static成员函数中调用static变量,但是不能调用非static成员变量。这是因为在对static函数调用时,可能还没有类的对象,让static函数可以调用非static变量是不合理的。
如下代码是可以正常运行的:
#include "iostream"using namespace std;class test{public:static int a;int b;test():b(10){}static void before_init(){cout<<a<<endl;}};int test::a=10;int main(void){test::before_init();return 0;}
在这个程序中,调用before_init()时还不存在test类的对象,若在before_init()函数中调用b,显然是错误的。而非static函数既可以调用非static变量,又可以调用static变量。

3.static函数和非static函数之间的互相调用

由2可知static函数不可以调用非static变量,但是非static函数可以调用非static变量。如果可以用static函数调用非static函数,岂不是间接的调用了非static变量吗?因此可以推断:非static函数可以调用static函数,而static函数不能调用非static函数。经过代码验证,此推断是正确的。

总结:对于static关键字在类中常见问题的分析,主要抓住一个顺序:即对static成员的处理是在类进行实例化之前的。