C++ 静态成员和静态成员函数

   在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。使用惊涛成员变量可以实现多个对象之间的数据共享而不会破坏隐藏的原则,

保证了安全性还可以节省内存。

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

   静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值。

    类的静态成员只能被定义一次,而且要被同类的所有对象共享。各个对象都拥有类中每一个普通数据成员的副本,但静态数据成员只有一个实例存在,与定义了多少类对象无关。静态方法就是与该类相关的,是类的一种行为,而不是与该类的实例对象相关。

     静态数据成员的用途之一是统计有多少个对象实际存在。

     静态数据成员在对象中不占用存储空间,这个属性为整个类所共有,不属于任何一个具体对象,所以不能再类中初始化,实际上类定义只是在描述对象的蓝图,在其中指定

初值是不允许的。也不能在类的构造函数中初始化该成员,因为静态数据成员为类的各个对象共享,否则每次创建一个类的对象则静态数据成员都要被重新初始化。

      静态成员的值对所有的对象都是一样的。静态成员可以被初始化,但只能在类体外进行初始化。

     一般形式:

                数据类型类名::静态数据成员名 = 初值    (注意:不能用参数初始化表对静态成员初始化。一般系统缺省初始为 0.)   

    下面举几个例子:

 1、通过类名调用静态成员函数和非静态成员函数

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:不能通过类名来调用类的非静态成员函数。


2、通过类的对象调用静态成员函数和非静态成员函数(点操作符,如 a.init(), a.output())


3、在类的静态成员函数中使用类的非静态成员

class Point
{
public:
	void init()
	{
	}
	static void output()
	{
		cout << "m_x" << endl;
	}
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   静态成员函数不能引用非静态成员。也可以说,静态成员函数没有隐含的 this 自变量,所以,无法访问自己类的非静态成员。


4、在类的非静态成员函数中使用类的静态成员

class Point
{
public:
	void init()
	{
		output();
	}
	static void output()
	{
	}
};
void main()
{
	Point pt;
	pt.output();
}
编译通过。

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


5、使用类的静态成员变量

class Point
{
public:
	Point()
	{
		m_nPointCount++;
	}
	~Point()
	{
		m_nPointCount--;
	}
	static void output()
	{
		cout << m_nPointCount << endl;
	}
private:
	static int m_nPointCount;
};
void main()
{
	Point pt;
	pt.output();
}
按Ctrl+F7编译无错误,按F7生成EXE程序是报链接错误。

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

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

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

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


    现总结如下:

    一、静态成员函数中不能调用非静态成员。

    二、非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。

    三、静态成员变量使用前必须先初始化(如 int MyClass::m_nNumber = 0 ;),否则会在 linker 是出错。

    四、出现在类体外的函数定义不能指定关键字 static;

    五、静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;

    六、因为没有 this 指针的开销,因此静态成员函数相比类的全局函数会在速度上有少许的增长。


   一般情况下,类中的 static 函数内的成员变量都要声明为 static,并且 static 成员还要显示初始化,有没有更好的方法呢?如下:

    

class a
{
public:
  static FunctionA(a* _a)
  {
    _a-> menber = 1;
 cout<<_a-> menber<<endl;
 _a->f();
  }
void f()
{
 cout<<"f被调用了"<<endl;
}
private:
  int menber;
};

  前提是这个类要分配了内存空间。其实这里做的就是将一个对象指针作为静态成员函数的 this 指针,模仿传递非静态成员函数里的 this 变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值