C++ 类的静态成员详细讲解

dannistang 2014-09-28

在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。

静态成员的定义或声明要加个关键static。静态成员可以通过双冒号来使用即<类名>::<静态成员名>。

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象。希望阅读本文可以使读者对类的静态成员变量和成员函数有更为深刻的认识。

将C语言梳理一下,分布在以下10个章节中:

  1. Linux-C成长之路(一):Linux下C编程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成长之路(二):基本数据类型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成长之路(三):基本IO函数操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成长之路(四):运算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成长之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成长之路(六):函数要义 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成长之路(七):数组与指针 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成长之路(八):存储类,动态内存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成长之路(九):复合数据类型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成长之路(十):其他高级议题

第一个例子,通过类名调用静态成员函数和非静态成员函数

class Point

{

public:   

      void init()

      { 

      }

      static void output()

      {

      }

};

void main()

{

      Point::init();

      Point::output();

}

编译出错:error C2352: 'Point::init' : illegal call of non-static member function

结论1:不能通过类名来调用类的非静态成员函数。

 

第二个例子,通过类的对象调用静态成员函数和非静态成员函数

将上例的main()改为:

void main()

{

      Point pt;

      pt.init();

      pt.output();

}

编译通过。

结论2:类的对象可以使用静态成员函数和非静态成员函数。

 

第三个例子,在类的静态成员函数中使用类的非静态成员

#include <stdio.h>

class Point

{

public:   

      void init()

      { 

      }

      static void output()

      {

              printf("%d\n", m_x);

      }

private:

      int m_x;

};

void main()

{

      Point pt;

      pt.output();

}

编译出错:error C2597: illegal reference to data member 'Point::m_x' in a static member function

因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间,所以这个调用就出错了,就好比没有声明一个变量却提前使用它一样。

结论3:静态成员函数中不能引用非静态成员。

 

第四个例子,在类的非静态成员函数中使用类的静态成员

class Point

{

public:   

      void init()

      { 

              output();

      }

      static void output()

      {

      }

};

void main()

{

      Point pt;

      pt.output();

}

编译通过。

结论4:类的非静态成员函数可以调用用静态成员函数,但反之不能。

 

第五个例子,使用类的静态成员变量

#include <stdio.h>

class Point

{

public:   

      Point()

      { 

              m_nPointCount++;

      }

      ~Point()

      {

              m_nPointCount--;

      }

      static void output()

      {

              printf("%d\n", m_nPointCount);

      }

private:

      static int m_nPointCount;

};

void main()

{

      Point pt;

      pt.output();

}

按Ctrl+F7编译无错误,按F7生成EXE程序时报链接错误

error LNK2001: unresolved external symbol "private: static int Point::m_nPointCount" (?m_nPointCount@Point@@0HA)

这是因为类的静态成员变量在使用前必须先初始化。

在main()函数前加上int Point::m_nPointCount = 0;

再编译链接无错误,运行程序将输出1。

结论5:类的静态成员变量必须先初始化再使用。

相关推荐