c++中静态成员变量为什么要在类外部再定义?否则产生link2001错误

qq24447678 2011-03-31 10:05:21
class testClass
{
public:
static int m_i;
};


int testClass::m_i;
//类外部定义,若不写会产生error LNK2001: unresolved external symbol "public: static int testClass::m_i" (?m_i@testClass@@2HA)


int main(int argc, char* argv[])
{
printf("%d\n",testClass::m_i);
printf("\n");
return 0;
}


能否说说是什么原因?
...全文
1979 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
zzhays 2012-09-24
  • 打赏
  • 举报
回复
静态成员变量是一个共享的数据成员,是属于整个类的(同样也是属于所有的对象的数据成员)而不专属于某一个对象,对于非静态数据成员,其专属于某个对象却跟类没关系;举个例子
class Data
{
public:
Data(){}
int a ;
static int b;
}
int Data::b=123;
int main()
{
Data *data1=new Data();
Data *data2=new Data();
return 0;
}
如果访问要访问 数据成员 int a,这就需要通过对象data1->a,或者data2->a;此时data1->a 和data2->a之间没有丝毫关系、二者相互独立;
但是如果访问静态数据成员 int b, 却要通过类来访问Data::b.这样来访问。data1 和data2指向的b值相同,任何一个更改了b值其余都会获得崭新的b值。
既然是属于类的就要一开始初始化,因为任何一个新的对象产生的时候都可能访问它,为了不照成错误,所以必须要最开始就初始化。
所以.....
purewqk 2011-04-01
  • 打赏
  • 举报
回复
静态变量都是和全局变量都是在数据段分配内存,所以静态变量就跟全局变量一样,需要在类外定义。
Zi_Yuan 2011-04-01
  • 打赏
  • 举报
回复
在类外部使用静态成员,如果没有生成该类的对象,则必须使用类名称和作用域解析运算符一起限定,如果生成了类对象,则也可以使用类对象名引用。
LBJMD 2011-03-31
  • 打赏
  • 举报
回复
书上就是这么说的,原因还真不清楚,mark,等高手指导。
daminglanyu 2011-03-31
  • 打赏
  • 举报
回复
因为在类的定义中仅仅对静态数据成员进行引用性说明,所以必须在文件作用域的某个地方用类名限定进行定义,这时也可以进行初始化。
jackiesen 2011-03-31
  • 打赏
  • 举报
回复
静态变量和普通变量的存储位置方式不同,所以访问时也不同!
quwei197874 2011-03-31
  • 打赏
  • 举报
回复
规定,因为在内存中存储位置不同.
pengzhixi 2011-03-31
  • 打赏
  • 举报
回复
类外定义一次这样才会分配内存。链接才不会出错。
ri_aje 2011-03-31
  • 打赏
  • 举报
回复
对于静态变量,类内部的那个叫声明,C++要求所有实体在任何翻译单元内必须有且只有一个定义,所以得在外部定义。
hukui161 2011-03-31
  • 打赏
  • 举报
回复
有些东西记着就好了。
ifengshow 2011-03-31
  • 打赏
  • 举报
回复
这个书上说的,理论的东西,我们了解知道些就行了
pathuang68 2011-03-31
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 forestdb 的回复:]

对于class的static data member,其实只是声明了一个scope(还记得class::static_data_member中的::么?),既然是声明而已,所以还需要一个定义,之所以需要在类的外面,因为本质来说它和global和static变量没什么区别,都是在数据段的,只是scope不一样,属于class而已。

这里反映出了C/C++里面一些稍微偏底层的复杂的细微的概念,……
[/Quote]

仔细看了7L的回复,觉得非常有道理。

1. 在类中,只是声明了静态变量,并没有定义。
2. 声明只是表明了变量的数据类型和属性,并不分配内存;定义则是需要分配内存的。
注意:如果在类里面这么写int a; 那么是既声明了变量,也定义了变量,两者合在一起了。
3. 静态成员是“类级别”的,也就是它和类的地位等同,而普通成员是“对象(实例)级别”的。类级别的成员,先于该类任何对象的存在而存在,它被该类所有的对象共享。
4. 现在,咱们假定要实例化该类的一个对象,那么会发生什么事情呢?静态成员肯定要出现在这个对象里面的,对吧?这时候才去定义那个静态成员吗?这显然是不合适的。因为,比如有另外一个线程也要创建该类的对象,那么也要按照这个方式去定义那个静态成员。这会产生两种可能的情况:1. 重复定义;2. 就算不产生重复定义的情况,也会产生竞争,从而造成死锁的问题,以至于对象无法创建。很显然,编译器不能这么干。那么很合理的解决办法,就是事先在类的外部把它定义好,然后再供所有的对象共享。当然这样做,还是有可能产生线程安全的问题,但不管怎么说对象是创建好了,而这种线程安全问题,可以在编程中予以解决。

这就是为什么要在类的外部进行定义的原因。

个人浅见,欢迎拍砖。
superhanxin5 2011-03-31
  • 打赏
  • 举报
回复
虽然是成员变量,但是,静态变量都是和全局变量在同一存储区存储的,程序初始化的时候它需要对该变量做初始化。
所以静态变量表现的就跟全局变量一样,需要在类外定义。
pathuang68 2011-03-31
  • 打赏
  • 举报
回复
参考这篇文章:
特殊数据类型成员变量的初始化

应该可以很好地解答楼主的问题。
ForestDB 2011-03-31
  • 打赏
  • 举报
回复
对于class的static data member,其实只是声明了一个scope(还记得class::static_data_member中的::么?),既然是声明而已,所以还需要一个定义,之所以需要在类的外面,因为本质来说它和global和static变量没什么区别,都是在数据段的,只是scope不一样,属于class而已。

这里反映出了C/C++里面一些稍微偏底层的复杂的细微的概念,比如scope,storage,life time。
::是指scope,是在class里面声明的,static指storage,是和global一样,在外面定义的。

64,644

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧