C++中成员变量加上static或const关键字后的分析

来源:互联网 发布:java switch 例子 编辑:程序博客网 时间:2024/05/20 18:04

C++中类成员变量加上static或const关键字后的初始化问题。在一个简单的C++类中定义如下这些变量:

[cpp] view plain copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class TestVariable{  
  6.     public:  
  7.     TestVariable(){}  
  8.     private:  
  9.     int intVariable;//情况0 不加限定符,这个不需要进行讨论  
  10.     const int constIntVariable;//情况1 const常量  
  11.     static int staticIntVariable;//情况2 静态变量  
  12.     static const int staticConstIntVariable;//情况3 静态常整型类型  
  13.     static const float staticConstNotIntVariable;//情况4 静态非常整型类型  
  14. };  
  15.   
  16. int main(){  
  17.     TestVariable variable;  
  18.     return 0;  
  19.   
  20. }  
加入限定符后多了4中情况,下面就这四种情况分别进行分析。

情况1:const修饰

编译上面的代码,首先在情况1处出现问题,在g++中的错误提示是:


在vs中的提示更明显,“error C2758: “TestVariable::constIntVariable”: 必须在构造函数基/成员初始值设定项列表中初始化”。直接给出了解决方法,就是说对于类中的const常量类型而言,需要在构造函数初始化化列表中进行初始化

[cpp] view plain copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class TestVariable{  
  6. public:  
  7.     TestVariable()<span style="color:#ff0000;">:constIntVariable(0)</span>{}  
  8. private:  
  9.     int intVariable;//情况0 不加限定符,这个不需要进行讨论  
  10.     const int constIntVariable;//情况1 const常量  
  11.     static int staticIntVariable;//情况2 静态变量  
  12.     static const int staticConstIntVariable;//情况3 静态常整型类型  
  13.     static const float staticConstNotIntVariable;//情况4 静态非常整型类型  
  14. };  
  15.   
  16. int main(){  
  17.     TestVariable variable;  
  18.     return 0;  
  19.   
  20. }  
这样情况1的问题就解决了。

情况2:static修饰

然后编译上面的代码能通过,不过明显还有问题,就是static变量没有初始化化,但是编译时没有出错。原因就是还没有使用到这些变量,因为static变量是类的所有实例共享的,所以在构造variable这个变量时只对constIntVariable这个变量进行了检查,在编译时会出错,但是其余的3个静态变量由于没有使用所有还看不出问题所在。将代码修改成这样来检查情况2中静态变量的问题:

[cpp] view plain copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class TestVariable{  
  6.     public:  
  7.     TestVariable():constIntVariable(0){}  
  8.   
  9.     <span style="color:#ff0000;">void printStaticInt(){  
  10.         cout<<"staticIntVariable:"<<staticIntVariable<<endl;  
  11.     }</span>  
  12.     private:  
  13.     int intVariable;//情况0 不加限定符,这个不需要进行讨论  
  14.     const int constIntVariable;//情况1 const常量  
  15.     static int staticIntVariable;//情况2 静态变量  
  16.     static const int staticConstIntVariable;//情况3 静态常整型类型  
  17.     static const float staticConstNotIntVariable;//情况4 静态非常整型类型  
  18. };  
  19.   
  20. int main(){  
  21.     TestVariable variable;  
  22.     variable.printStaticInt();  
  23.     return 0;  
  24.   
  25. }  
g++编译时的错误情况如下:



vs中的错误提示为“error LNK2001: 无法解析的外部符号 "private: static int TestVariable::staticIntVariable" (?staticIntVariable@TestVariable@@0HA)”,这种情况下g++中的提示更明显些,就是对TestVariable::staticIntVariable这个变量未定义的引用,所以我们的解决方法就是将它初始化。这个变量的初始化这样操作:

[cpp] view plain copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class TestVariable{  
  6.     public:  
  7.     TestVariable():constIntVariable(0){}  
  8.   
  9.     void printStaticInt(){  
  10.         cout<<"staticIntVariable:"<<staticIntVariable<<endl;  
  11.     }  
  12.     private:  
  13.     int intVariable;//情况0 不加限定符,这个不需要进行讨论  
  14.     const int constIntVariable;//情况1 const常量  
  15.     static int staticIntVariable;//情况2 静态变量  
  16.     static const int staticConstIntVariable;//情况3 静态常整型类型  
  17.     static const float staticConstNotIntVariable;//情况4 静态非常整型类型  
  18. };  
  19. <span style="color:#ff0000;">int TestVariable::staticIntVariable=1;</span>  
  20. int main(){  
  21.     TestVariable variable;  
  22.     variable.printStaticInt();  
  23.     return 0;  
  24.   
  25. }  

注意int TestVariable::staticIntVariable=1;这行代码不能写成static int TestVariable::staticIntVariable=1;,否则就在g++中会出现这个错误:


而在vs中会出现“error C2720: “TestVariable::staticIntVariable”: 成员上的“static ”存储类说明符非法”这个错误提示。

情况3:static const修饰的整型数据

然后就是情况3和情况4,情况3和情况4中的限定符是一样的,就是static const(这里写成static const和const static好像都可以,最起码在vs和g++中测试都通过了),不同的是数据类型而已,这里int类型是一种特例,就是静态常量整型(short ,int ,long,long long)数据可以在类中初始化,而其他类型都只能在类外面进行初始化。

首先添加调用这个变量的函数:

[cpp] view plain copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class TestVariable{  
  6.     public:  
  7.     TestVariable():constIntVariable(0){}  
  8.   
  9.     void printStaticInt(){  
  10.         cout<<"staticIntVariable:"<<staticIntVariable<<endl;  
  11.     }  
  12.   
  13.     <span style="color:#ff0000;">void printStaticConstInt(){  
  14.         cout<<"staticOnstIntVariable:"<<staticConstIntVariable<<endl;  
  15.     }</span>  
  16.     private:  
  17.     int intVariable;//情况0 不加限定符,这个不需要进行讨论  
  18.     const int constIntVariable;//情况1 const常量  
  19.     static int staticIntVariable;//情况2 静态变量  
  20.     static const int staticConstIntVariable;//情况3 静态常整型类型  
  21.     static const float staticConstNotIntVariable;//情况4 静态非常整型类型  
  22. };  
  23.  int TestVariable::staticIntVariable=1;  
  24. int main(){  
  25.     TestVariable variable;  
  26.     variable.printStaticInt();  
  27.     variable.printStaticConstInt();  
  28.     return 0;  
  29.   
  30. }  

在g++中编译的结果为:

用vs编译出错:“ error LNK2001: 无法解析的外部符号 "private: static int const TestVariable::staticConstIntVariable" (?staticConstIntVariable@TestVariable@@0HB)”,和情况2的错误提示是一样的。

只是它的定义方式有两种,在类内定义:

[cpp] view plain copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class TestVariable{  
  6.     public:  
  7.     TestVariable():constIntVariable(0){}  
  8.   
  9.     void printStaticInt(){  
  10.         cout<<"staticIntVariable:"<<staticIntVariable<<endl;  
  11.     }  
  12.   
  13.     void printStaticConstInt(){  
  14.         cout<<"staticOnstIntVariable:"<<staticConstIntVariable<<endl;  
  15.     }  
  16.     private:  
  17.     int intVariable;//情况0 不加限定符,这个不需要进行讨论  
  18.     const int constIntVariable;//情况1 const常量  
  19.     static int staticIntVariable;//情况2 静态变量  
  20.     <span style="color:#ff0000;">static const int staticConstIntVariable=3;//情况3 静态常整型类型</span>  
  21.     static const float staticConstNotIntVariable;//情况4 静态非常整型类型  
  22. };  
  23.  int TestVariable::staticIntVariable=1;  
  24. int main(){  
  25.     TestVariable variable;  
  26.     variable.printStaticInt();  
  27.     variable.printStaticConstInt();  
  28.     return 0;  
  29.   
  30. }  
在类外面定义:
[cpp] view plain copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class TestVariable{  
  6.     public:  
  7.     TestVariable():constIntVariable(0){}  
  8.   
  9.     void printStaticInt(){  
  10.         cout<<"staticIntVariable:"<<staticIntVariable<<endl;  
  11.     }  
  12.   
  13.     void printStaticConstInt(){  
  14.         cout<<"staticOnstIntVariable:"<<staticConstIntVariable<<endl;  
  15.     }  
  16.     private:  
  17.     int intVariable;//情况0 不加限定符,这个不需要进行讨论  
  18.     const int constIntVariable;//情况1 const常量  
  19.     static int staticIntVariable;//情况2 静态变量  
  20.     static const int staticConstIntVariable;//情况3 静态常整型类型  
  21.     static const float staticConstNotIntVariable;//情况4 静态非常整型类型  
  22. };  
  23.  int TestVariable::staticIntVariable=1;  
  24. <span style="color:#ff0000;"const int TestVariable::staticConstIntVariable=3;</span>  
  25. int main(){  
  26.     TestVariable variable;  
  27.     variable.printStaticInt();  
  28.     variable.printStaticConstInt();  
  29.     return 0;  
  30.   
  31. }  
注意,这里const这个关键字也需要,否则在g++中会出现这种错误提示:它会把它当成一个新的变量,但这个变量和原来的const类型的变量名相同,所以会出错。



在vs中的提示为:“error C2373: “staticConstIntVariable”: 重定义;不同的类型修饰符”。

情况4:static const修饰的非整型数据

然后就是情况4,对于静态常量非整型数据而言,如果在类内进行初始化:

[cpp] view plain copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class TestVariable{  
  6.     public:  
  7.     TestVariable():constIntVariable(0){}  
  8.   
  9.     void printStaticInt(){  
  10.         cout<<"staticIntVariable:"<<staticIntVariable<<endl;  
  11.     }  
  12.   
  13.     void printStaticConstInt(){  
  14.         cout<<"staticOnstIntVariable:"<<staticConstIntVariable<<endl;  
  15.     }  
  16.     void printStaticConstNotIntVariable(){  
  17.         cout<<"staticConstNotIntVariable:"<<staticConstNotIntVariable<<endl;  
  18.     }  
  19.     private:  
  20.     int intVariable;//情况0 不加限定符,这个不需要进行讨论  
  21.     const int constIntVariable;//情况1 const常量  
  22.     static int staticIntVariable;//情况2 静态变量  
  23.     static const int staticConstIntVariable;//情况3 静态常整型类型  
  24.     <span style="color:#ff0000;">static const float staticConstNotIntVariable=4.0;//情况4 静态非常整型类型</span>  
  25. };  
  26.  int TestVariable::staticIntVariable=1;  
  27.  const int TestVariable::staticConstIntVariable=3;  
  28. int main(){  
  29.     TestVariable variable;  
  30.     variable.printStaticInt();  
  31.     variable.printStaticConstInt();  
  32.     variable.printStaticNotIntVariable();  
  33.     return 0;  
  34.   
  35. }  
在g++中没有问题:

在vs 2008中会出现这个错误“error C2864: “TestVariable::staticConstNotIntVariable”: 只有静态常量整型数据成员才可以在类中初始化”。

所以最好还是不要写这种代码吧。

将变量的初始化放在类外面和情况3一样就可以了:

[cpp] view plain copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class TestVariable{  
  6. public:  
  7.     TestVariable():constIntVariable(0){}  
  8.   
  9.     void printStaticInt(){  
  10.         cout<<"staticIntVariable:"<<staticIntVariable<<endl;  
  11.     }  
  12.   
  13.     void printStaticConstInt(){  
  14.         cout<<"staticOnstIntVariable:"<<staticConstIntVariable<<endl;  
  15.     }  
  16.     void printStaticConstNotIntVariable(){  
  17.         cout<<"staticConstNotIntVariable:"<<staticConstNotIntVariable<<endl;  
  18.     }  
  19. private:  
  20.     int intVariable;//情况0 不加限定符,这个不需要进行讨论  
  21.     const int constIntVariable;//情况1 const常量  
  22.     static int staticIntVariable;//情况2 静态变量  
  23.     static const int staticConstIntVariable;//情况3 静态常整型类型  
  24.     static const float staticConstNotIntVariable;//情况4 静态非常整型类型  
  25. };  
  26. int TestVariable::staticIntVariable=1;  
  27. const int TestVariable::staticConstIntVariable=3;  
  28. <span style="color:#ff0000;">const float TestVariable::staticConstNotIntVariable=4.0;</span>  
  29. int main(){  
  30.     TestVariable variable;  
  31.     variable.printStaticInt();  
  32.     variable.printStaticConstInt();  
  33.     variable.printStaticConstNotIntVariable();  
  34.     return 0;  
  35.   
  36. }  

这种情况在g++中和vs中运行的结果就都是正确的了。


最后关于static,它在类中和在类外使用时有不同的含义,这里总结一下:

1.函数体内的static变量的作用范围为该函数体,不同于auto变量,该变量的内存只能被分配一次,因此其值在下次调用时仍维持上次的值。

2.在模块内的static全局变量可以被模块内的所有函数访问,但不能被模块外其它函数访问。

3.在模块内的static函数只可能被这一模块内的其它函数调用,这个函数的使用范围被限定在声明它的模块内。

4.在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝。

5.在类中的static成员函数属于整个类所拥有,这个函数不接受this指针,因此只能访问类的static成员变量。

原创粉丝点击