我们可以使用static关键字把类成员定义为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。
静态成员在类的所有对象都是贡献的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为0。我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化。
静态成员变量
/*** static.cpp ***/ #include<iostream> using namespace std;class Box {public:static int objectCount;Box(double l = 2.0,double b = 2.0,double h = 2.0){cout << "Construct called." << endl;length = l;breadth = b;height = h;objectCount++;}double Volume(){return length*breadth*height;}private:double length;double breadth;double height; };int Box::objectCount = 0;int main() {Box box1(3.3,1.2,1.5);Box box2(8.5,6.0,2.0);cout << "Total object: " << Box::objectCount << endl; return 0;}
运行结果:
exbot@ubuntu:~/wangqinghe/C++/20190807$ g++ static.cpp -o static
exbot@ubuntu:~/wangqinghe/C++/20190807$ ./static
Construct called.
Construct called.
Total object: 2
静态成员函数:
如果把函数成员声明为静态的,就可以把函数和类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也可以被调用,静态函数只要使用类名加范围解析运算符::就可以访问。
静态成员函数只能访问静态成员数据、其他静态成员函数和类外部的其他函数。
静态成员函数有一个类范围,他们不能访问类的this指针。也可以使用静态成员函数来判断类的某些对象是否被创建。
静态成员函数和普通成员函数的区别:
静态成员函数没有this指针,只能访问静态成员(包括静态成员变量和静态成员函数)
普通成员函数有this指针,可以访问类中的任意成员;而静态成员函数没有this指针。
/*** staticfun.cpp ***/ #include<iostream> using namespace std;class Box {public:static int objectCount;Box(double l = 2.0,double b = 2.0,double h = 2.0){cout << "Construct called." << endl;length = l;breadth = b;height = h;objectCount++;}double Volume(){return length*breadth*height;}static int getCount(){return objectCount;}private:double length;double breadth;double height; };int Box::objectCount = 0;int main() {cout << "Init stage count: " << Box::getCount() << endl;Box box1(3.3,1.2,1.5);Box box2(8.5,6.0,2.0);cout << "final stage count: " << Box::getCount() << endl; return 0; }
运行结果:
exbot@ubuntu:~/wangqinghe/C++/20190807$ g++ staticfun.cpp -o staticfun
exbot@ubuntu:~/wangqinghe/C++/20190807$ ./staticfun
Init stage count: 0
Construct called.
Construct called.
final stage count: 2
静态成员变量在类中仅仅是声明,没有定义,所以要在类的外面
定义,实际上是给静态成员变量分配内存,如果不加定义就会报错,初始化是赋一个初始值,而定义是分配内存。
利用静态成员变量来了解构造和析构函数的调用情况。
#include<iostream> using namespace std;class Cpoint {public:static int value;static int num;Cpoint(int x,int y){xp = x;yp = y;value++;cout << "call construct " << value << endl;}~Cpoint(){num++;cout << "call deconstruct " << num << endl;}private:int xp;int yp; };int Cpoint::value = 0; int Cpoint::num = 0;class CRect {public:CRect(int x1,int x2):mpt1(x1,x2),mpt2(x1,x2){ cout << "call construct" << endl; }~CRect(){cout << "call deconstruct" << endl;}private:Cpoint mpt1,mpt2; };int main() {CRect p(10,20);cout << "hello world!" << endl;return 0; }
运行结果:
exbot@ubuntu:~/wangqinghe/C++/20190807$ g++ construct.cpp -o construct -g
exbot@ubuntu:~/wangqinghe/C++/20190807$ ./construct
call construct 1
call construct 2
call construct
hello world!
call deconstruct
call deconstruct 1
call deconstruct 2
类中特殊成员变量的初始化问题:
- 常量变量:必须通过构造函数参数列表进行初始化
- 引用变量:必须通过构造函数参数列表进行初始化
- 普通静态变量:要在类外通过“::”初始化
- 静态整型变量:可以直接在定义的时候初始化
- 静态非整型常量:不能直接在定义的时候初始化。要在类通过”::”初始化