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

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

C++const static static constconst static的初始化以及修改问题

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

由于字数限制,在下只好把一篇完整的博客以连载的形式分几次发表,由此给大家带来的不便,还请大家多多包涵,予以谅解。下面开始进入正题。

一、conststaticstatic constconst static变量的初始化

.const的初始化

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

class Myclass

{

cons int a;//注意,在任何情况下,const int aint 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()

{   //在大括号下面出现下划线报错:ErrorMyclass ::Myclass()未提供初始值设定项。这是因为类中有const常量所以编译器提示在写构造函数时要提供初始化列表。

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

}

private:

const int b;

}

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

正确做法:

#include <iostream>

using namespace std;

Class Myclass

{

public

Myclassint bz:(b)bz{};

int Getdata()

{

return b;

}

private:

const int b;

};

void main()

{

 Myclass obj(1);

cout<<obj. Getdata()<<endl;//输出1

}

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,初始化意味着为ab分配内存,而我们知道,类是抽象的,并不占用内存,编译器编译时,根据类的数据成员计算出类的大小,但不进行内存分配操作(见注释②)。只有在实例化对象时,才为对象分配内存。如果初始化数据成员,一方面,初始化要分配内存,另一方面,声明类不分配内存,这显然是矛盾的。

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

总之,在下个人认为,不能在类内初始化const与不能初始化int a的道理是一样的。

前面我们说过,类中的const数据成员在该类的不同对象间是可变的,及同一类的不同对象中可以不同。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现,或者static const。关于static const,后面将详细讨论,至于枚举常量本文所讨论的重点,我们也只给出一个简单的例子。

class Myclass

{

private

enum {size1=100, size2 = 200 };

}

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

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

                                                                                                                                                                                                                                                                                        (未完待续)

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