一、静态数据成员
子:在类的数据成员声明前加上关键词是static,那么该数据成员就成为了类内的静态数据成员,我们看一个例
#include<iostream>
using namespace std;
class Point
{
private:
int x, y;
static int num; //声明静态数据成员
public:
Point()
{
x = y = 0;
num++;
cout << num << endl;
}
};
int Point::num = 0; //定义静态数据成员
int main()
{
Point a;
Point b;
Point c;
Point d;
return 0;
}
对于类的非静态数据成员,每个类对象都有自己的拷贝。而对于静态数据成员被当作是类的成员。就像上述例子中,虽然定义了4个对象,但是静态数据成员在程序中只有一份拷贝,由该类型的所有对象共享访问。对于这个类的多个对象来说,静态数据成员只分配一次内存,可以供所有的对象共用。因此,对于每个对象来说静态数据成员的值都是相同的,可以更新。
上面说了静态数据成员与非静态数据成员的区别,那么它的特点如下:
- 静态数据成员的存储位置是在全局数据区。当它定义的时候要分配空间,所以它不能在类声明中定义,要在类的外部定义并初始化,像上面的例子,若不初始化,则默认初始化为0;
- 静态数据成员和普通的数据成员都要遵从public,protected,private的访问规则;
- 对于它的访问形式有两种: <类对象名>.<静态数据成员名>或者<类类型名>::<静态数据成员名>
我们定义静态数据成员有几个好处如下:
- 静态数据成员在内存只占用一份空间,每个对象都可以引用它,它的值对每个对象都是一样的。我们改变了它的值那么在每个对象中这个数据的成员的值都发生了改变。
- 正是因为它在内存中只占用一份空间,这样还可以节约空间,提高效率。
- 有了它我们就可以实现多个对象之间的数据共享。
- 它还可以实现数据的隐藏,把它定义为private成员
有些特点我们通过全局变量也可以实现,那我们为什么还选择静态数据成员:全局变量破坏了封装的原则,不符合我们面向对象程序的要求,而且静态全局成员没有进入程序的全局的名字空间,所以我们不会存在程序中与它全局名字冲突的可能性。
二、静态成员函数
静态成员函数和静态数据成员是类似的。它是为类的全部服务而不是为了某一个类的具体对象服务的。它和
静态数据成员一样都是在类的内部实现的,属于类定义的一部分。普通的成员函数都是具体属于某个类的具体对象的,一般都隐含一个this指针,通常情况下this是缺省的。与普通成员函数相比,静态成员函数不与任何一个对象相联系,所以它不具有this指针。从这个方面说,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其他的静态成员函数。下面看一个静态成员函数的例子:
#include<iostream>
using namespace std;
class Point
{
private:
int x, y;
static int num; //声明静态数据成员
public:
Point()
{
num++;
}
static void showsumofpoint(); //声明静态成员函数
};
int Point::num = 0; //定义静态成员函数
void Point::showsumofpoint() //定义静态成员函数
{
cout << num << endl;
}
int main()
{
Point a;
a.showsumofpoint();
Point b;
b.showsumofpoint();
Point c;
Point::showsumofpoint();
Point d;
Point::showsumofpoint();
return 0;
}
静态成员函数有以下几点需要注意的:
- 在类体外部的函数定义不能指定关键字static;
- 静态成员之间可以相互访问;
- 非静态成员函数可以任意的访问成员函数和静态数据成员;
- 静态成员函数不能访问非静态成员数和非静态数据成员;