目录
在阅读本文之前,建议先阅读博主的另一篇关于static关键字的文章:static 关键字_static是在函数声明时加还是定义时加-优快云博客,该文章对 static
关键字进行了详细解析,阅读后将有助于更轻松地理解本篇内容!!
———————————————————————————————————————————
一、静态成员介绍
静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员。
静态成员分为:
- 静态成员变量
1. 所有对象共享同一份数据【这是因为static
修饰的类成员变量属于整个类,而不是某个对象】
2. 在编译阶段分配内存
3. 类内声明,类外初始化 - 静态成员函数
1. 所有对象共享同一个函数【静态成员函数属于类本身,不属于某个具体对象】
2. 静态成员函数可以访问静态成员变量,因为静态成员变量属于整个类,而不是某个对象。
3. 静态成员函数无法访问非静态成员变量,因为它们没有this
指针(不依赖对象)。
4. 静态成员函数也是有访问权限的。若静态成员函数被private修饰,类外部不能调用静态成员函数。
二、static 修饰类成员变量【静态成员变量】
下面的代码说明什么叫做static修饰的类成员变量必须在类内声明类外定义并初始化:
先尝试在类内初始化static修饰的类成员变量是错误的做法,示例代码如下:
class A {
static int classVar = 2; // ❌ 错误:非 const 的 static 变量不能在类内初始化
};
编译器报错:
然后在类内声明static修饰的类成员变量,在类外初始化,这种做法是正确的,示例代码如下:
class A {
static int classVar; // 只声明,不占用对象的内存
};
int A::classVar = 10; // 定义并初始化
static
修饰的类成员变量 classVar 属于整个类,而不是某个对象。- classVar 静态变量存储在静态存储区(全局区),但作用域受类限制。
正确代码示例:
#include<iostream>
class A {
public:
static int classVar; // 只声明,不占用对象的内存
// static修饰的类内成员变量有什么特点?
// static int classVar; 不属于任何一个对象,而属于整个类。它只在全局/静态数据区存储一份,所有对象共享它。
// 编译阶段分配内存
// 类内声明,类外初始化
};
int A::classVar =10; //类外初始化static修饰的类内成员变量 ✅ 这里才真正分配存储空间
int main(){
// 静态成员变量的两种访问方式:
// 方式1:通过对象访问类内静态成员变量
A a1; // 实例化对象a1
std::cout<< a1.classVar<<std::endl; // 输出10
A a2; // 实例化对象a2
a2.classVar=100; // 修改classVar的值
std::cout<<a1.classVar<<std::endl; // 输出100
// 方式2:通过作用域去访问
std::cout<<A::classVar<<std::endl; // 输出100
return 0;
}
私有static修饰的类成员变量外部不可访问,示例代码如下:
#include<iostream>
class A {
private:
static int classVar; // 只声明,不占用对象的内存
};
int A::classVar =10; //类外初始化static修饰的类内成员变量
int main(){
A a1; // 实例化对象a1
// std::cout<< a1.classVar<<std::endl; // ❌编译错误:member "A::classVar" (declared at line 8) is inaccessible
return 0;
}
三、static 修饰的类成员函数【静态成员函数】
所有对象共享同一个静态成员函数 。因为静态成员函数不属于任何一个对象,它属于类,因此所有对象共享同一个静态成员函数。
静态成员函数的访问方式:
- 方式1:通过对象去访问静态成员函数
- 方式2:通过【类名::静态成员函数】作用域的方式去访问
示例代码如下:
#include<iostream>
class A {
public:
// 静态成员函数
// 所有对象共享同一个静态成员函数
// 静态成员函数只能访问静态成员变量,不能访问非静态成员变量
static void func(){
std::cout<< "static void func被调用"<<std::endl;
}
};
int main(){
// 实例化两个对象
A a1;
A a2;
a1.func(); // 通过对象访问静态成员函数
a2.func();
A::func(); // 通过类名作用域访问静态成员函数
return 0;
}
静态成员函数只能访问静态成员变量,不能访问非静态成员变量。
#include<iostream>
class A {
public:
static int m_A; // 类内声明静态成员变量
int m_a; // 定义一个非静态成员变量
// 静态成员函数
static void func(){
std::cout<< "static void func被调用"<<std::endl;
std::cout<<"静态成员变量 m_A的值为:"<<m_A<<std::endl;
// std::cout<<"非静态成员变量 m_a的值为:"<<m_a<<std::endl; // ❌编译错误:a nonstatic member reference must be relative to a specific object
}
};
int A::m_A=10; // 类外初始化静态成员变量
int main(){
A a1;// 实例化对象
a1.func(); // 通过对象访问静态成员函数
return 0;
}
// 输出:
// static void func被调用
// 静态成员变量 m_A的值为:10
静态成员函数 func()
不能访问非静态成员变量 m_a
,因为 静态成员函数不属于某个具体对象,而 m_a
是对象级的变量。