个人看法:静态成员变量和静态成员函数属于类,而不属于某一个具体的对象。它们只在类的范围内有效,供所有的类对象访问和使用。
静态成员变量
(0) 类的静态成员拥有一块单独的存储区,而不管创建了多少个该类的对象。所有这些对象的静态数据成员都共享这一块静态存储空间,这就为这些对象提供了一种互相通信的方法。静态数据成员是属于类的,它只在类的范围内有效。
(1) 静态数据成员的声明通常会放在一个类的实现文件中。在文件中定义(初始化)静态成员容易引起重复定义定义的错误。比如头文件同时被多个.cpp文件所包含的时候,即使加上#ifndef #define #endif或者#pragma once也不行。
(2) C++静态数据成员被类的所有对象所共享,包括该类的派生类的对象。派生类对象与基类对象共享基类的静态数据成员。静态的数据成员在内存中只占一份空间,如果改变它的值,则在各个对象中这个数据成员的值同时都改变了,这样可以节约空间,提高效率。
(3)如果只声明了类而未定义对象,类的一般数据成员是不占内存空间的,只有在定义对象时才会为对象的数据成员分配空间。但是静态数据成员不属于某一个对象,所以在为对象所分配的空间中不包括静态数据成员所占的空间,静态数据成员是在所在对象之外单独开辟一段空间来存放。只要在类中定义了静态数据成员,即使不定义对象,也为静态数据成员分配了空间,它可以被引用。
(4) 如果在一个函数中定义了静态变量,在函数结束时该静态变量并不被释放,仍然存在并保留其值。静态数据成员也类似,它不随对象的建立而分配空间,也不随对象的撤销而释放。静态数据成员是程序在编译时被分配空间,到程序结束时释放空间。
(5)静态数据成员可以通过对象名引用,也可以通过类名来引用。
静态成员函数
(0)静态成员函数也是类的一部分,而不是对象的一部分。如果要在类外调用公用的静态成员函数,要用类名和域运算符"::"。
(1)静态函数的存在是为了能处理静态数据成员。非静态成员函数有this指针,而静态成员函数没有this指针。由此决定了静态成员函数不能访问本类中的非静态成员。
(2)为什么静态成员函数不能访问非静态成员?
当调用一个对象的成员函数(非静态成员函数)时,系统会把该对象的起始地址赋给成员函数的this指针。而静态成员函数并不属于某一对象,它与任何对象都无关,因此静态成员函数没有this指针。既然它没有指向某一对象,也就无法对一个对象中的非静态成员进行默认访问(即在引用数据成员时不指定对象名)。
(3) 使用习惯:只用静态成员函数引用静态数据成员,而不引用非静态数据成员。这样思路比较清晰、逻辑更清楚,不易出错。(在静态成员函数中并不是绝对不能引用本类中的非静态成员,只是不能进行默认访问,因为无法知道应该去找那个对象。如果一定要引用本类的非静态成员,应该加对象名和成员运算符".",比如函数参数传入本类对象)
(4)静态数据成员必须在类的外部定义。在非静态成员函数中可以使用静态数据成员、非静态数据成员。而在静态成员函数中则可以不加类名直接引用静态数据成员。
class test
{
public:
int a1; // 非静态成员变量
static int a2; // 静态成员变量
static void fun(test &t); // 静态成员函数
};
// 类外定义静态成员变量
int test::a2 = 100;
// 类外定义静态成员函数
void test::fun(test &t)
{
// 静态成员函数中访问静态成员变量
a2 = 100;
// 静态成员函数中访问非静态成员变量,不建议
t.a1 = 10000;
}
内容来自:《后台开发 核心技术与应用实践》