• static关键字修饰成员变量与成员函数


    1. static概念

    声明static的类成员称为类的静态成员,用static修饰的成员变量,称为静态成员变量;用static修饰的成员函数,称为静态成员函数,都存放在堆区。

    静态成员变量一定要在类外进行初始化

    为什么静态成员变量一定要在类外进行初始化呢?

    1. 在类中,仅仅是声明了静态变量(告诉我们有这个成员变量),并没有定义(定义需要分配内存)。

    2. 声明只是表明了变量的数据类型和属性,并不分配内存;定义则需要分配内存。 注意:如果在类里面这么写 int a ;那么既声明了变量,也定义了变量,两者合在一起了。

    3. 静态成员是“类级别的”,它和类的地位等同,而普通成员是“对象(实例)级别的”。类级别的成员,先于该类的任何对象而存在,是属于所有对象的,被该类的所有对象共享。

    4. 现在,咱们假定要实例化该类的一个对象,那么会发生什么事情呢?

      静态成员肯定要出现在这个对象里面的,对吧?这时候才去定义那个静态成员吗?显然不合适!因为,比如有另外一个线程也要创建该类的对象,那么也要按照这个方式去定义那个静态成员。
      这可能会产生两种情况:
      A. 重复定义;
      B. 就算不产生重复定义的情况,也会产生竞争,造成死锁。
      显然编译器不能这么干。很合理的解决办法,就是在类的外部事先把它定义好,然后再供所有的对象共享。

    class A
    {
    public:
    	static int _a;
    	static int _b;
    };
    
    int A::_a = 10;   // 定义静态成员变量,同时也初始化。
    int A::_b;   // 定义静态成员变量,不初始化也可以。
    
    int main()
    {
    	A T1;
    	cout << T1._a << endl;  // 10
    	cout << A:: _b << endl;  // 0
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    静态成员函数既可以在类内定义,也可以在类外定义,类外定义不需要加static。

    普通成员函数可以访问所有成员(包括成员变量和成员函数),静态成员函数只能访问静态成员。

    编译器在编译一个普通成员函数时,会隐式地增加一个形参 this,并把当前对象的地址赋值给 this,所以普通成员函数只能在创建对象后通过对象来调用,因为它需要当前对象的地址。而静态成员函数可以通过类来直接调用,编译器不会为它增加形参 this,它不需要当前对象的地址,所以不管有没有创建对象,都可以调用静态成员函数。

    普通成员变量占用对象的内存,静态成员函数没有 this 指针,不知道指向哪个对象,无法访问对象的成员变量,也就是说静态成员函数不能访问普通成员变量,只能访问静态成员变量。

    普通成员函数必须通过对象才能调用,而静态成员函数没有 this 指针,无法在函数体内部访问某个对象,所以不能调用普通成员函数,只能调用静态成员函数。

    class A
    {
    public:
    	A() { ++_count; }
    
    	A(const A& t) { ++_count; }
    	
    	~A() { --_count; }
    	
    	static int GetACount()    // 类内定义,只能访问静态成员
    	{
    		return _count; 
    	}
    
    private:
    	static int _count;
    };
    
    int A::_count = 0;
    
    
    void TestA()
    {
    	cout << A::GetACount() << endl;   // 可以直接调用类
    	A a1, a2;
    	A a3(a1);
    	cout << a3.GetACount() << endl;   // 也可以直接使用对象调用
    }
    
    int main()
    {
    	TestA();
    
    	return 0;
    }
    
    • 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

    总结:
    静态成员函数与普通成员函数的根本区别在于:普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。

    2. 使用细节

    特性:

    1. 静态成员为所有类对象共享,存放在静态区(在对象实例化之前就已经定义了)。
    2. 静态成员变量必须在类外定义,定义时不添加static关键字。
    3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问。
    4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。
    5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制。

    3. 易错点

    问题1:
    静态成员函数可以调用非静态成员函数吗?
    不可以,因为静态成员函数没有this指针,普通成员函数必须有相应的对象地址(this)才能调用,因为普通函数里面要用this来访问对象。

    问题2:
    非静态成员函数可以调用类的静态成员函数吗?
    可以,静态成员函数属于整个类,既可以使用类域(A::)进行调用,也可以使用对象(a1.)进行调用。

  • 相关阅读:
    贪吃蛇和俄罗斯方块
    使用Spring Cloud设计电商系统架构
    Qt Designer生成ui文件,如何转py文件,如何运行
    Android MVI架构的深入解析与对比
    00后如何组织双十一大促看这一篇就够了! | 京东云技术团队
    企业计算机服务器中了mallox勒索病毒怎么解决,勒索病毒解密文件恢复
    学习笔记3--传感器技术
    聚观早报 | 新一代iPad 10取消耳机孔;哈啰电动车推出小哈修车
    NNDL 实验八 网络优化与正则化(6)网络正则化
    深度伪造相关代码/工具
  • 原文地址:https://blog.csdn.net/weixin_45153969/article/details/132791791