C++中const、static、 static const和const static的初始化以及

2019-08-30 11:35

C++中const 、static、 static const和const

static的初始化以及修改问题

本人系C++初学者,很渣很菜鸟,这也是本人写的第一篇有关C++的博文 ,说是写,不如说是对网络上高人博文的综合与整理。(当然,凡是本文涉及到别人博客内容的,都将附上网址链接。)写这篇博文的目的,是希望对相关知识做出尽可能全面、详尽、简易的解释,以供像我一样的初学者参考,同时也希望得到高人的批评与指正,以此来提高自己。另外,为保证文章的针对性,同时也限于本人水平,本文只对相关类型的数据做出讨论,并不涉及函数的讨论。下面,是我的一些整理与见解。

一、const、static、static const、const static变量的初始化

Ⅰ.const的初始化

(1)只有这一种情况const变量可以不在声明的同时定义,那就是const变量作为类的数据成员出现时。例如: class Myclass {

cons int a;//注意,在任何情况下,const int a与int const a等价,只不过人们习惯写前者 };

但要注意,这样做是毫无意义的,只是编译能够通过罢了,int const a什么也做不了,因为它没有值。

(2)凡是在函数(包括类中的,main函数及其它)中,const常量必须在声明时初始化,这是因为const被视为常量。例如: class Myclass() {

public: int test() {

const int b; ?? }

当输入int const b;一句时,在分号下面出现红色下划线,鼠标移到该处,出现报错:Error:常量 变量 “b”需要初始值设定项。(注意,在本文中,以后这种情况我们简称为“下划线报错”)

在main函数、全局函数中情况相似。 (3)作为全局常量 在全局中写

const int b;// 即不在类中,不在函数中

写代码时不会出现下划线,但编译时报错:如果不是外部的,则必须初始化常量对象。 注意这里的“外部的”是指声明为extern的常量。即将上句改为extern const int b;则可编译通过。因为声明为extern,就是在告诉编译器const int b是一个将在后面定义的变量。当然,如果只写extern const int b而不在其后对b赋值的话,也是毫无意义的(b没值,什么也干不了)。

关于xetern的详细情况,见注释①。

(3)如何初始化

1)作为类的数据成员

只能通过构造函数的初始化列表来初始化。注意在构造函数的函数体内初始化是不行的,见下例: class Myclass {

public:

Myclass()

{ //在大括号下面出现下划线报错:Error:Myclass ::Myclass()未提供初始值设定

项。这是因为类中有const常量所以编译器提示在写构造函数时要提供初始化列表。

b=1; //b下下划线报错:Error:表达式必须是可修改的左值 } private: const int b; };

对于这种情况,我们可以试着这样解释: b=1;写在函数体内,被看成是一条赋值语句,(这从报错“表达式必须是可修改的左值”可以看出)而b是常量,这当然是不允许的。 正确做法:

#include using namespace std; Class Myclass {

public:

Myclass(int bz):(b)bz{}; int Getdata() {

return b; } private: const int b; };

void main() {

Myclass obj(1);

cout<

2)其它地方的const常量

都可以直接初始化,即const int b=1;都可以。 最后,关于const ,再简单说两点。 ⒈为什么不能在类内初始化const? 关于这一点,网上最普遍的说法是:

const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么。

但依本人愚见,更为主要的原因是:const数据成员是类内(in_class)成员(即类的不同对象中const数据成员的值可以不同)const int b;与int a;的不同仅在于,在一个对象中,a可以改b不可以改。无论对a还是b,初始化意味着为a和b分配内存,而我们知道,类是抽象的,并不占用内存,编译器编译时,根据类的数据成员计算出类的大小,但不进行内存分配操作(见注释②)。只有在实例化对象时,才为对象分配内存。如果初始化数据成员,一方面,初始化要分配内存,另一方面,声明类不分配内存,这显然是矛盾的。

另外,对多个对象而言,const是变量,如果在类内初始化const的话,那么由该类创建的多个对象中的const相同,这和我们的初衷是相违背的。

总之,在下个人认为,不能在类内初始化const与不能初始化int a的道理是一样的。 ⒉前面我们说过,类中的const数据成员在该类的不同对象间是可变的,及同一类的不同对象中可以不同。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现,或者static const。关于static const,后面将详细讨论,至于枚举常量本文所讨论的重点,我们也只给出一个简单的例子。 class Myclass {

private:

enum {size1=100, size2 = 200 }; };

这里只给出初始化的形式,至于为什么size1、size2是整个类中都恒定的常量,就不给出验证的代码了,本人在这一块也不精通,但可以告诉大家,对size1、size2进行再赋值,取地址等操作是不可以的,编译器直接报错。有兴趣的读者可以自行深入探究,当然也欢迎将结果告知在下。

本小节最后,向大家推荐一篇文章《const的思考》,(百度可见)本人感觉这篇文章相对来说写得比较专业,同时全面易懂,应该出自大神之笔,大家看了应该会有所收获。 Ⅱstatic的初始化

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

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

②初始化一次性: 无论是静态局部变量还是静态全局变量,都只初始化一次。 ③记忆性:所谓”记忆性”是指在两次函数调用时, 在第二次调用进入时, 能保持第一次调用退出时的值,直至重新赋值。static具有全局唯一性的特点, 每次调用时, 都指向同一块内存。 eg.

#include

using namespace std; void ceshi1() { for(int i=0;i<3;i++){ int k=0; k++; cout<

void ceshi2() {

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

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型初始化为0,char型自动初始化为

ASSIC码值为0的字符(NULL),但一定注意,此时初始化语句还是要写,只不过不赋右值,例如int Myclass::a;(见例5)

? 静态数据成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式为:

<数据类型><类名>::<静态数据成员名>=<值> ? 类的静态数据成员有两种访问形式:

<类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名> 如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式来引用静态数据成员 ;

? 静态数据成员主要用在各个对象都有相同的某项属性的时候。比如对于一个存款类,

每个实例的利息都是相同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局数据区的内存,所以节省存储空间。第二,一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了;

? 同全局变量相比,使用静态数据成员有两个优势:

1. 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲

突的可能性;

2. 可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能; 以上总结来自http://blog.csdn.net/jsjwql/article/details/1788286 。 例1:

#include 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<

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


C++中const、static、 static const和const static的初始化以及.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:河北省唐山一中11-12学年高二下学期期末考试数学文试题

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: