静态成员
写在前面
在类定义中,它的成员(包括成员变量和成员函数),这些成员可以用关键字static
声明为静态的,称为静态成员。
不管这个类创建了多少个对象,静态成员只有一个拷贝,这个拷贝被所有属于这个类的对象共享。
1.静态成员变量
在一个类中,若将一个成员变量声明为static
,这种成员变量称为静态成员变量。与一般的数据成员不同,无论建立多少个对象,都只有一个静态数据的拷贝。静态成员变量,属于某个类,所有对象共享。
静态变量,是在编译阶段就分配空间,对象还没创建,就已经分配空间。
- 静态成员变量必须在类中声明,在类外定义
- 静态数据成员不属于某个对象,在为对象分配空间中不包括静态成员所占的空间
- 静态数据成员可以通过类名或者对象名来引用
#include <iostream>
using namespace std;
class Person
{
public:
static int m_Age;
private:
static int m_other;
};
int Person::m_Age = 100;
int Person::m_other = 20;
void test()
{
Person p1;
p1.m_Age = 10;
cout << "p1=" << p1.m_Age << endl;
cout << "p1的地址为:" << &p1.m_Age << endl;
Person p2;
p2.m_Age = 20;
cout << "p1=" << p1.m_Age << endl;
cout << "p2=" << p2.m_Age << endl;
cout << "p2的地址为:" << &p2.m_Age << endl;
}
int main()
{
test();
}
输出结果如下图:
通过输出结果我们可以很清除地看到,静态成员变量是所有对象共享的。任何一个对象都可以改变静态变量的值,但是静态变量不属于任何一个对象。
下面我们看一下对象的大小,以此来说明静态数据成员不属于某个对象,在为对象分配的空间中不包括静态成员所占的空间。
#include <iostream>
using namespace std;
class Person
{
public:
static int m_Age;
private:
static int m_other;
};
int Person::m_Age = 100;
int Person::m_other = 20;
void test()
{
Person p;
cout << sizeof(p) << endl;
cout << sizeof(p.m_Age) << endl;
}
int main()
{
test();
}
输出结果如下图:
我们可以看出,对象的大小为1,而静态成员佰利联的大小为4。
当我们尝试去访问m_other时,编译器会报错,因为它是一个私有数据成员,这也说明了静态成员变量是有权限控制机制的。
2.静态成员变量
在类定义中,前面有static
说明的成员函数称为静态成员函数。静态成员函数使用方式和静态变量一样,同样在对象没有创建前创建,即可他通过类名调用。静态成员函数主要为了访问静态变量,但是不能访问普通成员变量。
静态成员函数的意义,不在于信息共享,数据沟通,而在于管理静态数据成员,完成对静态数据成员的封装。
- 静态成员函数只能访问静态变量,不能访问普通成员变量
- 静态成员函数的使用和静态成员变量一样
- 静态成员函数也有访问权限
- 普通成员函数可以访问静态成员变量,也可以访问非静态变量
如上图所示,当我们使用静态成员函数试图访问非静态成员变量时,编译器会报错,提示信息如上图所示。
在上图中,我试图使用类名来访问私有的静态成员函数,编译器报错,因为静态成员函数也有自己的权限。
#include <iostream>
using namespace std;
class Person
{
public:
static void func()//静态成员函数
{
m_Age = 100;
//m_A = 20;//作用域
cout << "静态成员函数调用" << endl;
}
static int m_Age;
int m_A;
private:
static int m_other;
static void func01()
{
cout << "静态成员函数func2调用" << endl;
}
};
int Person::m_Age = 100;
int Person::m_other = 20;
void test()
{
Person p1;
Person p2;
p1.func();
p2.func();
Person::func();
//Person::func01();//作用域
}
int main()
{
test();
}
输出结果如下图:
3.总结
- 静态成员变量
- 编译阶段分配内存
- 所有对象共享数据
- 通过对象访问,通过类名访问
- 有权限控制
- 类内声明,类外初始化
- 静态成员函数
- 可以访问静态成员变量,不可以访问普通成员变量
- 普通成员函数都可以访问
- 静态成员函数也有权限
- 可以通过对象访问,也可以通过类名访问