1 静态成员变量

静态成员变量是C++中与类本身相关联而非与类的实例相关联的成员变量。它们在所有类的实例之间共享,所有对象访问的都是同一份数据

1.1 基本特性

静态成员变量具有以下几个重要特点:

  • 共享性​:所有类的对象共享同一个静态成员变量,任何对象对它的修改都会影响其他对象。
  • 内存分配​:静态成员变量在编译阶段就分配内存,位于全局数据区,程序结束时才释放。
  • 初始化要求​:静态成员变量必须在类外进行初始化(C++17后允许inline静态成员在类内初始化)。

1.2 声明与初始化

静态成员变量的声明使用static关键字,但初始化必须在类外部进行:

class Jeff
{
public:
    static int _hight; // 静态成员变量声明
    // ... 其他成员
};

int Jeff::_hight = 179; // 静态成员变量初始化

如果不进行类外初始化,链接阶段会出现"无法解析的外部符号"错误

1.3 访问方式

静态成员变量可以通过两种方式访问:

  1. 通过对象名​:h._hight
  2. 通过类名​:Jeff::_hight

两种访问方式访问的是同一内存地址,这一点可以通过打印地址来验证

2 静态成员函数

静态成员函数是属于类本身而非类的实例的函数

。它们不依赖于任何对象实例,因此可以在没有创建类实例的情况下调用。

2.1 基本特性

静态成员函数具有以下特点:

  • 与对象无关​:静态成员函数没有隐式的this指针,因此不能直接访问类的非静态成员。
  • 共享性​:所有对象共享同一个静态成员函数。
  • 调用方式​:可以通过类名直接调用,也可以通过对象调用。

2.2 定义与使用

class Hero
{
public:
    static int _getcount() // 静态成员函数
    {
        return _herocount; // 只能访问静态成员变量
    }
private:
    static int _getcount1() // 私有静态成员函数
    {
        return _herocount;
    }
    // ... 其他成员
};

2.3 访问限制

静态成员函数只能访问静态成员变量和其他静态成员函数,不能访问非静态成员变量和非静态成员函数

。这是因为静态成员函数没有this指针,无法确定要访问哪个对象的成员。

如果需要在静态成员函数中访问非静态成员,必须通过传递对象实例作为参数

static void displayValue(Hero& obj)
{
    cout << "Value: " << obj._name << endl; // 通过对象访问非静态成员
}

3 静态成员的内存特性

3.1 内存分配时机

静态成员变量在程序编译时就分配内存,而不是在创建对象时分配

。这意味着:

  • 静态成员变量在对象创建之前就已经存在
  • 静态成员的生命周期与程序的生命周期相同
  • 静态成员的内存位于全局数据区,而不是对象的堆栈空间中

3.2 内存共享机制

由于所有对象共享同一份静态成员数据,因此

  • 静态成员变量不占用对象的存储空间
  • 对静态成员的任何修改都会影响所有对象
  • 可以通过任意对象或类名访问和修改静态成员

4 访问控制与封装

静态成员同样遵循类的访问控制规则

  • 公有静态成员​:可以在类外直接访问
  • 私有静态成员​:只能在类内部访问,需要通过公有接口访问
  • 保护静态成员​:只能在类内部和派生类中访问
class Hero
{
public:
    static int getCount() { return _getcount1(); } // 公有接口访问私有静态函数
private:
    static int _getcount1() { return _herocount; } // 私有静态函数
};

5 应用场景

静态成员在C++编程中有多种应用场景

5.1 对象计数器

通过静态成员变量可以统计类的实例数量:

class MyClass
{
public:
    MyClass() { ++count; }
    ~MyClass() { --count; }
    static int getCount() { return count; }
private:
    static int count;
};

int MyClass::count = 0;

5.2 单例模式

静态成员常用于实现单例模式,确保一个类只有一个实例

class Singleton
{
public:
    static Singleton* getInstance()
    {
        if (instance == nullptr)
            instance = new Singleton();
        return instance;
    }
private:
    static Singleton* instance;
    Singleton() {} // 私有构造函数
};

Singleton* Singleton::instance = nullptr;

5.3 常量共享

静态常量成员可以在所有对象间共享常量值:

class MathConstants
{
public:
    static const double PI;
    static const double E;
};

const double MathConstants::PI = 3.14159;
const double MathConstants::E = 2.71828;

6 总结

C++中的静态成员变量和静态成员函数是与类本身相关联而非与对象实例相关联的成员

。它们具有以下核心特性:

  1. 共享性​:所有对象实例共享同一份静态成员。
  2. 内存分配​:静态成员在编译阶段分配内存,位于全局数据区。
  3. 访问方式​:可以通过类名直接访问,无需创建对象实例。
  4. 限制​:静态成员函数只能访问静态成员,不能访问非静态成员。
  5. 初始化​:静态成员变量必须在类外初始化(C++17前)。

静态成员在许多场景下非常有用,如实现对象计数器、单例模式、共享常量等

。正确使用静态成员可以提高代码的效率和可维护性,但同时需要注意其共享特性可能带来的线程安全问题。

7.0源码及运行:

#include<iostream>
#include<string>
using namespace std;


//静态变量特点:
//1.所有对象共享一份数据
//2.编译阶段分配内存
//3.类内声明变量,类外初始化
class Jeff
{
public:Jeff() :_name("Nolan"), age(18) {};//初始化变量
	  
	  ~Jeff() {};

	  static int _hight;//静态变量声明

private:
	string _name;
	int age;
};
int Jeff::_hight = 179;//静态变量初始化,注释改行将无法运行

int main()
{
	Jeff h;
	cout << h._hight << endl;//如果不初始化则无法运行,无法解析外部指令
	h._hight = 156;//赋其他值,可以覆盖前面的值,
	cout << Jeff::_hight << endl;//第二种种打印的方法。
	//至此可以看看他们是否在同一个定义域,打印他们的地址就行,就是两种输出方式的地址是否相同
	cout <<&( h._hight) << endl;
	cout << &(Jeff::_hight) << endl;
	//通过运行结果可知相同

	return 0;
}
#include<iostream>
#include<string>
using namespace std;
class Hero
{
public:
	Hero() :_name("jett"), _hp(100) {};
	

	static int _herocount;
	static int _getcount()//声明静态函数
	{
		//_name = "666";//会报错,因为用了普通成员对象
		return _herocount;
	}

private:
	string _name;
	int _hp;
	static int _getcount1()//声明静态函数
	{
		//_name = "666";//会报错,因为用了普通成员对象
		return _herocount;
	}
};

int Hero::_herocount = 50;



int main()
{
	Hero h;

	cout << h._getcount() << endl;//打印函数返回值,两种方式
	cout << Hero::_getcount() << endl;
	//cout << Hero::_getcount1() << endl;//报错因为他是私有变量,在外部无法访问,要一个接口,
	return 0;
}

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐