技术交流QQ群:1027579432,欢迎你的加入!
1.Cpp中类的静态成员
- 可以使用static关键字来把类成员定义为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符::来重新声明静态变量从而对它进行初始化,如下面的实例所示:
#include "iostream" using namespace std; class Box{ public: static int count; // 声明一个静态成员变量! Box(double l, double w, double h): length(l), width(w), height(h){ cout << "这是Box类对象的构造函数....\n"; count++; // 每创建一个Box类的对象时,count增加1 } double getVolume(){ return length * width * height; } private: double length; double width; double height; }; // 静态成员变量要在类外初始化! int Box::count = 0; int main(){ Box box1(3.2, 1.4, 5.5); Box box2(6.6, 4.2, 8.7); cout << "Box类总共的对象数是: " << Box::count << endl; return 0; }
2.静态成员函数
- 如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符::就可以访问。静态成员函数只能访问静态成员数据、其他静态成员函数和类外部的其他函数。
- 静态成员函数有一个类范围,它们不能访问类的this指针。可以使用静态成员函数来判断类的某些对象是否已被创建。静态成员函数与普通成员函数的区别:
- 静态成员函数没有this指针,只能访问静态成员(包括静态成员变量和静态成员函数);
- 普通成员函数有this指针,可以访问类中的任意成员,而静态成员函数没有this指针
- 静态成员函数实例如下:
#include "iostream" using namespace std; class Box{ public: static int count; // 声明一个静态成员变量! Box(double l, double w, double h): length(l), width(w), height(h){ cout << "这是Box类对象的构造函数....\n"; count++; // 每创建一个Box类的对象时,count增加1 } double getVolume(){ return length * width * height; } // 静态成员函数定义!!! static int getCount(){ return count; } private: double length; double width; double height; }; // 静态成员变量要在类外初始化! int Box::count = 0; int main(){ // 在创建对象前输出对象的总数 cout << "未创建对象前的对象数是: " << Box::getCount() << endl; Box box1(3.2, 1.4, 5.5); Box box2(6.6, 4.2, 8.7); cout << "Box类总共的对象数是: " << Box::getCount() << endl; return 0; }
- 类的静态成员细节知识
- 静态成员变量在类中仅仅是声明,没有定义。所以要在类的外面定义,实际上是给静态成员变量分配内存。如果不加定义就会报错,初始化是赋一个初始值,而定义是分配内存。
#include "iostream" using namespace std; class Box{ public: static int count; // 声明一个静态成员变量! Box(double l, double w, double h): length(l), width(w), height(h){ cout << "这是Box类对象的构造函数....\n"; count++; // 每创建一个Box类的对象时,count增加1 } double getVolume(){ return length * width * height; } private: double length; double width; double height; }; // 初始化类Box的静态成员 ,其实是定义并初始化的过程 int Box::count = 0; // 也可这样 定义却不初始化 int Box::count; int main(){ Box box1(3.2, 1.4, 5.5); Box box2(6.6, 4.2, 8.7); cout << "Box类总共的对象数是: " << Box::count << endl; return 0; }
- 可以使用静态成员变量清楚了解构造与析构函数的调用情况
// 可以使用静态成员变量清楚了解构造与析构函数的调用情况 class Cpoint{ public: static int value; static int num; Cpoint(int x, int y): xp(x), yp(y){ value++; cout << "调用构造: " << value << endl; cout << this->xp << " " << this->yp << endl; } ~Cpoint(){ num++; cout << "调用析构: " << num << endl; } private: int xp; int yp; }; // 静态成员变量初始化 int Cpoint::num = 0; int Cpoint::value = 0; class CRect{ public: CRect(int x1, int x2): mpt1(x1, x2), mpt2(x1, x2){ cout << "调用构造\n"; } ~CRect(){ cout << "调用析构\n"; } private: Cpoint mpt1, mpt2; }; CRect p(10, 20); cout << "hello world!\n";
- 上述程序的分析:构造p时,先调用CRect的构造函数,在使用初始化列表初始化字段mpt1和mpt2时,又调用Cpoint的构造函数两次;析构p时,先调用CRect的析构函数并输出,然后析构成员mpt1和mpt2,且顺序是先调用mpt2的析构函数,再调用mpt1的析构函数。发现析构的过程和构造过程完全相反
class Cpoint{ public: static int value; static int num; Cpoint(int x, int y): xp(x), yp(y){ value++; cout << "调用构造: " << value << endl; cout << this->xp << " " << this->yp << endl; } ~Cpoint(){ num++; cout << "调用析构: " << num << endl; cout << this->xp << " " << this->yp << endl; } private: int xp; int yp; }; // 静态成员变量初始化 int Cpoint::num = 0; int Cpoint::value = 0; class CRect{ public: CRect(int x1, int x2): mpt1(x1, x1), mpt2(x2, x2){ cout << "调用构造\n"; } ~CRect(){ cout << "调用析构\n"; } private: Cpoint mpt1, mpt2; }; CRect p(10, 20); cout << "hello world!\n";
- 上述程序的分析:构造p时,先调用CRect的构造函数,在使用初始化列表初始化字段mpt1和mpt2时,又调用Cpoint的构造函数两次;析构p时,先调用CRect的析构函数并输出,然后析构成员mpt1和mpt2,且顺序是先调用mpt2的析构函数,再调用mpt1的析构函数。发现析构的过程和构造过程完全相反
- 静态成员变量在类中仅仅是声明,没有定义。所以要在类的外面定义,实际上是给静态成员变量分配内存。如果不加定义就会报错,初始化是赋一个初始值,而定义是分配内存。