C++中const 、static、 static const和const static的初始化以及修改问题(2)

作者在 2014-06-12 00:19:23 发布以下内容

static的初始化

1)首先,浅析一下static数据。

static数据,即静态数据,它有以下特点:

①全局性:static(无论局部static还是全局static)分配在静态(或称全局)存储区, 在程序整个运行期间都不释放.(但要注意:见注释

②初始化一次性: 无论是静态局部变量还是静态全局变量,都只初始化一次。

③记忆性:所谓记忆性是指在两次函数调用时, 在第二次调用进入时, 能保持第一次调用退出时的值,直至重新赋值。static具有全局唯一性的特点, 每次调用时, 都指向同一块内存。

eg.

#include<iostream>

using namespace std;

void ceshi1()

{

         for(int i=0;i<3;i++){

                   int k=0;

                   k++;

                   cout<<k<<endl;

         }

}

void ceshi2()

{

    for(int i=0;i<3;i++){

                   static int t=0;

                   t++;

                   cout<<t<<endl;

         }

}

void main ()

{

 ceshi1();//输出1 1 1

ceshi2();//输出1 2 3

}

④作用域限定性:函数或变量前加static使得函数成为静态函数,变量成为静态变量。此时,函数的作用域仅局限于本文件(所以又称内部函数)。注意,此时, 对于外部(全局)变量, 不论是否有static限制, 它的存储区域都是在静态存储区, 生存期都是全局的. 此时的static只是起作用域限制作用, 限定作用域在本模块(文件)内部.

以上①②③④参考自http://blog.csdn.net/Kendiv/article/details/675941,读者可进一步了解更多细节。

特别的,对类的static数据成员,有

静态数据成员有以下特点:

  • 对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问。也就是说,静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。 即静态数据成员独立于对象之外,放在一个单独的区域(静态数据区),为同一类的所以对象共享。(见例1、例4
  • 静态数据成员的值对每个对象都是一样的,但它的值可以改,一改全改;比如,原来,在类中声明ctatic int a;在类外初始化为1,则在该类的每一个对象中,a值为1,后来,将a该为2,则此时,在该类的每个对象中,a值为2;(见例4
  • 静态数据成员存储在静态数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义(即初始化)。(见例2、例3
  • 静态数据成员和普通数据成员一样遵从public, protected, private访问规则,private, protected static成员虽然可以在类外初始化,但是不能在类外被访问。
  • static成员变量的初始化是在类外,因为static变量不是类的非静态数据成员,注意此时不能再带上static的关键字。(见例2、例3、例4
  • 因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它; (见例5
  • 若不对静态数据成员初始化,系统自动将int型初始化为0char型自动初始化为ASSIC码值为0的字符(NULL),但一定注意,此时初始化语句还是要写,只不过不赋右值,例如int  Myclass::a;(见例5
  • 静态数据成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式为:
    <数据类型><类名>::<静态数据成员名>=<值>
  • 类的静态数据成员有两种访问形式:
    <类对象名>.<静态数据成员名> <类类型名>::<静态数据成员名>
    如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式来引用静态数据成员
  • 静态数据成员主要用在各个对象都有相同的某项属性的时候。比如对于一个存款类,每个实例的利息都是相同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局数据区的内存,所以节省存储空间。第二,一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了;
  • 同全局变量相比,使用静态数据成员有两个优势:
  1. 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性;
  2. 可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能;

以上总结来自http://blog.csdn.net/jsjwql/article/details/1788286

1

#include<iostream>

using namespace std;

class Myclass

{

public:

Myclass(int a=0,char b=0,float c=0 ){}

private:

int a;

char b;

float c;

static int d;

};

int Myclass::d=1;

void main()

{

Myclass obj(1,'a',1.0);

cout<<sizeof(obj)<<endl;//输出12

}

由此可以看出,对象obj指向的内存的大小就是int achar bfloat c的大小,不包括static int d,由此可知static不属于具体对象。其实,前三者存在栈区,后一者存在静态数据

区。至于char b占一个字节,为什么输出是12,这是编译系统进行内存对齐的缘故。至于对齐,还是那句话,不是重点不展开,相信读者自己能够解决。

2(这里我们只给出代码段,说明问题即可)

class Myclass

{

public:

Myclass(int az):a(az){}//a下下划线报错:Error:“a”不是类“Myclass”的非静态数据成

private:              //或基类

static int a;//也可以写成int static a;

};

这说明不能通过构造函数初始化列表初始化static数据成员。

3

#include<iostream>

using namespace std;

class Myclass

{

public:

         Myclass(int az)  //企图通过构造函数,在函数体内对static int a 初始化

         {

                   a=az;

         }

         int re_a()

         {

                   return a;

         }

private:   

         static int a;

};

void main ()

         {

                   Myclass obj(1);

                   cout<<obj.re_a()<<endl;

         }

写代码时不会出现下划线报错,但编译过不去,有类似“一个无法解释的外部命令”的报错。

4

#include<iostream>

using namespace std;

class Myclass

{

public:

         int re_a()

         {

                   return a;

         }

         void chong_fu_zhi()

         {

                   a=2;

         }

private:   

         static int a;

};

int  Myclass::a=1;

//static int  Myclass::a=1;//如果这样写,会出现下划线报错:Error:此处不能指定存储类

void main ()

         {

                   Myclass obj1,obj2;

                   cout<<obj1.re_a()<<endl;//输出1

                   cout<<obj2.re_a ()<<endl;//输出1

                   obj1.chong_fu_zhi();//注意这里只是修改obj1a,但a值一改全改,这恰说明a

                   cout<<obj1.er_a i()<<endl;//输出2       //为所有对象共享

                   cout<<obj2.re_a ()<<endl;//输出2

         }

5

#include<iostream>

using namespace std;

class Myclass

{

public:

static int a;

static int b;

static char c;

};

int  Myclass::a=1;

int  Myclass::b;

int  Myclass::c;

void main()

{

cout<< Myclass::a<<endl;//输出1      //未实例化对象就可以对static 数据进行操作

cout<< Myclass::b<<endl;//输出0

cout<< Myclass::a<<endl;//输出空格(ASSIC码值为0的是NULL

}

2)如何初始化

前面说的够多了,见例4就可以了。

                                                                               (未完待续)

C++ | 阅读 3293 次
文章评论,共0条
游客请输入验证码
浏览37045次
文章分类
文章归档
最新评论