本文最后更新于:1 年前
(一)概念:
类成员冠以static声明时,称为静态成员。静态成员用于解决类内数据共享的问题,既能够避免使用全局变量,又能够让同类的多个对象数据共享。
如果使用全局变量对封装的类来说并不安全,因为其他的类外函数能共享、修改全局变量,同时容易发生名字的冲突问题。
静态成员包括静态数据成员和静态成员函数。
下面分别介绍。
(二)静态数据成员:
1. 概念:
c++类中声明数据成员时, 加上static关键字声明的成员成为静态数据成员。
形式:类内:static 数据类型 变量名; 声明
类外:数据类型 类名::变量名=值; / 数据类型 类名::变量名; 定义和初始化
2. 特点:
-
类中的静态数据成员遵守public、protected、private规则,但是只能在类中进行声明,不允许在类中进行定义和初始化(为了避免产生多个对象时多次定义初始化导致值的改变,导致数据变化。在类外一经定义必须初始化。
-
被类的所有对象共享,只有一份内存,保存在静态存储空间中,其生命周期和整个程序相同。独立于所有对象——即使没有对象也存在,能够被访问、赋值。本质上,静态数据成员是全局变量。
-
可以通过对象访问静态数据成员,也可以通过类名::静态数据成员的方法去访问。
-
静态数据成员可以作为成员函数的默认参数值,其类型可以是所属类的类型(普通数据成员均不可)。
-
静态数据成员在常成员函数中可以修改。(因为this指针指向对象const但静态数据成员不是对象的)
-
sizeof运算符计算对象所占用的存储空间时,不会将静态成员变量计算在内。类大小=非静态成员数据的类型大小之和。
3. 代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include<iostream> using namespace std; class Point { private: double x, y; public: static int pointcounter; Point() { x = 0; y = 0; pointcounter++; } Point(double x, double y) { this->x = x; this->y = y; pointcounter++; } void move(double x, double y) { this->x = x; this->y = y; } double getX() { return x; } double getY() { return y; } ~Point() { pointcounter--; } }; int Point::pointcounter = 0; int main() { cout << "现存点数:" << Point::pointcounter << endl; Point* p1 = new Point(1, 1); Point* p2 = new Point(2, 2); Point* p3 = new Point(3, 3); cout << "现存点数:" << Point::pointcounter << endl; delete p1; delete p2; cout << "现存点数:" << Point::pointcounter << endl; delete p3; cout << "现存点数:" << Point::pointcounter << endl; return 0; }
|
(三)静态成员函数:
1. 概念:
静态成员函数是指用static修饰的成员函数。
静态成员函数的作用不是为了对象之间的沟通,而是为了能处理静态数据成员。
形式:static 返回类型 函数名( 参数表) { 函数体 }
2.特点:
-
静态成员函数不属于某一对象,因此静态成员函数没有this指针(与成员函数的根本区别),其本质是一个全局函数。
-
静态成员函数只能够访问静态成员变量,但可以直接引用本类中的静态数据成员,因无this指针,不能够默认访问一个对象中的非静态成员。
-
静态成员函数的实现可以在类体内,也可以在类体外。
-
静态成员函数的调用可以通过类,也可以通过对象,且无需对象就可以调用静态成员函数。
-
(附):静态成员函数不是绝对不能引用非静态成员,只是不能进行默认访问,因为不知道要找哪个对象,如果一定要引用,需要加对象名和成员运算符“.”。(不建议使用)
3.代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| #include<iostream> using namespace std; class Point { private: double x, y; public: static int pointcounter; static void addpointconuter() { pointcounter++; return; } static void delpointconuter(); Point() { x = 0; y = 0; pointcounter++; } Point(double x, double y) { this->x = x; this->y = y; pointcounter++; } void move(double x, double y) { this->x = x; this->y = y; } double getX() { return x; } double getY() { return y; } ~Point() { pointcounter--; } } p; void Point::delpointconuter() { this->x = this->y = 0; p.x = p.y = 0; pointcounter = 0; } int Point::pointcounter = 0; int main() { Point* p1 = new Point(1, 1); Point* p2 = new Point(2, 2); Point* p3 = new Point(3, 3); cout << "现存点数:" << Point::pointcounter << endl; Point::addpointconuter(); cout << "现存点数:" << Point::pointcounter << endl; Point::delpointconuter(); cout << "现存点数:" << Point::pointcounter << endl; delete p1; delete p2; cout << "现存点数:" << Point::pointcounter << endl; delete p3; cout << "现存点数:" << Point::pointcounter << endl; return 0; }
|