免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2555 | 回复: 6
打印 上一主题 下一主题

对书上const 数据成员解释的疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-09-24 12:06 |只看该作者 |倒序浏览
不能在类声明中初始化const 数据成员。以下用法是错误的,因为类的对象未被创
建时,编译器不知道SIZE 的值是什么。
class A
{…
     const int SIZE = 100; // 错误,企图在类声明中初始化const 数据成员
     int array[SIZE]; // 错误,未知的SIZE
};


"因为类的对象未被创建时,编译器不知道SIZE 的值是什么"这句话是什么意思呀?

[ 本帖最后由 yjcq 于 2006-9-24 12:24 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2006-09-24 12:46 |只看该作者

  1. #include <iostream>

  2. class Object
  3. {
  4. public:
  5.     static const int size = 100;
  6.     static int number;
  7. };

  8. Object::number = 0;

  9. int main()
  10. {
  11.     std::cout << "size of Object is " << sizeof(Object) <<std::endl;
  12.     return 0;
  13. }

复制代码


  1. #include <iostream>

  2. class Object
  3. {
  4. public:
  5.     const int size ;
  6.     int number;
  7. };

  8. int main()
  9. {
  10.     std::cout << "size of Object is " << sizeof(Object) <<std::endl;
  11.     return 0;
  12. }
复制代码


运行一下上面的代码,看看结果有什么不同.

c++中类的成员可以分为类属成员和实例成员.

类属成员是依附与类的,不必创建类的实例(对象)就可以存在的,一般使用static关键字来修饰.一般使用时,通过 类名::成员名来引用.

实例成员,就是通常我们所看到的,通过型如 Object obj或Object *pObj = new Object这种形式,首先创建一个类的实例,然后使用其成员的形式.

这两种情况的区别就在于类属数据成员不占用类实例的存储空间,它是在编译期就可以确定的,类似于C编译器对static变量的处理.

而实例数据成员,只有在创建类的实例后才存在,这是个运行期的概念--只有在程序执行后.


  1. class A
  2. {…
  3.      const int SIZE = 100; // 错误,企图在类声明中初始化const 数据成员
  4.      int array[SIZE]; // 错误,未知的SIZE
  5. };
复制代码

你的代码里面,如果改成static const int SIZE = 100;这样就可以了,因为编译器在编译期就可以确定静态成员的数据,或者早期的c++编译器使用匿名枚举来完成同一功能

  1. class A
  2. {
  3.        enum {SIZE = 100};
  4.        int array[SIZE];
  5. };
  6. class A
  7. {
  8.       static const int SIZE = 100;
  9.       int array[SIZE];
  10. }
复制代码


编译器能否编译成功主要取决于编译器能否正确推导出类的实例的尺寸.

论坛徽章:
0
3 [报告]
发表于 2006-09-24 12:48 |只看该作者
static const int SIZE = 100;
或者
enum
{
  SIZE = 100
};

论坛徽章:
0
4 [报告]
发表于 2006-09-24 14:32 |只看该作者
类属数据成员不占用类实例的存储空间,它是在编译期就可以确定的
而实例数据成员,只有在创建类的实例后才存在,这是个运行期的概念--只有在程序执行后.
这二句话是什么意思呀?跟可执行文件中的.text,.bss段有关系吗?

论坛徽章:
0
5 [报告]
发表于 2006-09-25 08:55 |只看该作者
二楼的兄弟,
偶之前一段代码,用枚举替换了类里的static const int后,
生成的可执行文件大小,由46K降到了26K,
不解啊,请教一下其中的道理

论坛徽章:
0
6 [报告]
发表于 2006-09-26 12:43 |只看该作者
>>类属数据成员不占用类实例的存储空间,它是在编译期就可以确定的
>>而实例数据成员,只有在创建类的实例后才存在,这是个运行期的概念--只有在程序执行后.
>>这二句话是什么意思呀?跟可执行文件中的.text,.bss段有关系吗?

.text一般是指代码段,.bss即未初始化数据段.

c语言里,对于静态和外部变量,都是存放在数据段内的.在编译完成,生成目标文件后,在目标文件里,就已经为其保留了空间,或者为其设置了初始化值,或者在程序被loader载入时,初始化为0--所以我说它是个编译期的概念,因为在编译完成后,就可以认为该变量已经存在了,它已经占据了存储空间了.

还有一种在堆栈内或是在堆里面分配的变量,这种变量只有在程序执行时,执行到该函数内部,通过调整堆栈指针来分配空间并进行初始化等操作,这一切都是在程序成为进程运行时才得以实现的,所以说它是个运行期的概念.


  1. class Object
  2. {
  3. private:
  4.       static int sharedValue;
  5.       int instanceValue;
  6. };

  7. 被编译器逻辑处理为

  8. struct Object
  9. {
  10.       int instanceValue;
  11. };    // 每个Object类的实例(无论它创建于堆栈还是堆还是数据段)均有其各自独立的instanceValue值,所以称其为实例变量

  12. static int sharedValue;  // 所有Object的实例(哪怕根本没有创建对象也存在)所共享的,因为它实际上就相当于一个全局变量.

  13. static const int SIZE = 100;
  14. 通过static使编译器将其分配在数据段--在编译完成就分配存储空间,通过使用const告诉编译器这是一个常量,可用于
  15. const int ARRAY_SIZE = 100;
  16. int array[ARRAY_SIZE];这样的语法里.

  17. 我让你比较尺寸的目的就是让你了解类属成员不占用类实例的存储空间,从而了解这种存储分配的布局情况.


复制代码





>>偶之前一段代码,用枚举替换了类里的static const int后,
>>生成的可执行文件大小,由46K降到了26K

c++里面的const默认采用的是internal linkage(除非你加extern声明).可能编译器做的是为你的每个使用该常量的编译单元产生了一份该常量的拷贝.你用nm检查一下目标文件看一下,看如果有该符号的话,看它是"U"还是其它什么的--如果是"U"表示它是存在与外部的某个目标文件里,如果是其他的,那么编译器应当是生成拷贝了--因为他是个const.

enum默认采用的是external linkage.

论坛徽章:
0
7 [报告]
发表于 2006-09-26 19:09 |只看该作者
1楼回答正确!!^_^!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP