静态成员变量和静态成员函数在C++类中的作用

本文详细解析了C++中static关键字的用法,包括在面向过程和面向对象设计中的应用。介绍了静态全局变量、静态局部变量及静态函数的特点,并重点讲解了静态数据成员和静态成员函数的概念、初始化方式及其使用场景。

为了便于理解,我们先来说说面向过程设计中的static,对理解面向对象设计中的static多少会有些裨益,也可以加深大家对这方面知识的理解。面向过程中设计中的static主要从以下几个方面来进行说明:

  • 静态全局变量,在其他文件中可以定义相同的名字而不会发生冲突;
  • 静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到一下次的调用,直到下次赋值;
  • 静态函数只能在声明它的文件当中可见,不能被其他文件使用,在其他文件中可以定义相同名字的函数,不会发生冲突。

面向对象设计中的static
一、静态数据成员
1、概念
静态数据成员在全局数据区分配内存,而非静态成员需要实例化才会分配内存。
对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问,所以静态数据成员的值对每个对象都是一样的,它的值可以更新。
而对于非静态数据成员,当类别实例化后,可以通过实例化的类名进行访问,非静态数据成员的生存期取决于该类的生存期,而且每个类对象都有自己的拷贝。而静态成员则不存在生存期的概念,因为静态数据成员始终驻留在内存中。
2、静态数据成员初始化
静态数据成员初始化与一般数据成员的初始化不同,

<数据类型><类名>::<静态数据成员> = <>;
eg:int MyClass::sum = 0;

静态数据成员主要用在各个对象都有相同的某项属性的时候。eg:存款类,每个对象的利息相同,所以把利息设为静态数据成员。
好处:1、不管定义多少个存款类的对象,利息数据成员都共享分配在全局数据区的内存,所以节省了存储空间;2、一旦利息需要改变是,只要改变一次,则所有存款类对象的利息全部改变过来了。

二、静态成员函数
1、概述
静态成员函数为类全部服务,而不是为类的具体某一个对象服务。
2、普通成员函数和静态成员函数的区别
普通成员函数一般都隐藏了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。
一般,this指针是缺省的,但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。从这个意义上讲,静态成员函数无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。
3、举例说明

#include <iostream>
using namespace std;

class MyClass {
public:
    MyClass(int a,int b,int c);
    static void func();
private:
    int a, b, c;
    static int sum;
};
int MyClass::sum = 0;

MyClass::MyClass(int a,int b,int c)
{
    this->a = a;
    this->b = b;
    this->c = c;
    sum += a + b + c;
}

void MyClass::func()
{
    cout << "sum=" << sum << endl;
}

void main()
{
    MyClass M(1, 2, 3);
    M.func();

    MyClass N(4,5,6);
    N.func();

    MyClass::func();// 静态成员函数的访问

    return;
}

运行结果:
这里写图片描述

由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比,速度上会有少许的增长。需要总结一点的是,静态成员不能访问非静态成员,非静态成员可以直接访问类中的静态成员。

### 静态成员变量作用 静态成员变量中所有对象共享的成员变量,它不属于某个具体的对象,而是属于整个静态成员变量通常用于存储与相关的全局信息,例如记录的实例数量、共享资源的管理等。 静态成员变量的内部声明,但必须在外部进行定义初始化,否则会导致链接错误。例如,在以下代码中,`count`是`MyClass`的静态成员变量,用于记录创建的对象数量: ```cpp class MyClass { public: MyClass() { count++; } // 每次构造对象时增加计数 ~MyClass() { count--; } // 每次析构对象时减少计数 static int GetCount() { return count; } // 静态成员函数访问静态变量 private: static int count; // 内声明 }; int MyClass::count = 0; // 外定义并初始化 ``` 静态成员变量具有作用域,可以通过名或对象访问。例如: ```cpp MyClass obj1; MyClass obj2; std::cout << MyClass::GetCount() << std::endl; // 输出 2 ``` 静态成员变量也可以是私有的,这种情况下外无法直接访问,只能通过静态成员函数间接访问[^1]。 --- ### 静态成员函数作用 静态成员函数是用`static`关键字修饰的成员函数,它与普通成员函数的主要区别在于没有`this`指针,因此不能访问的非静态成员变量,只能访问静态成员变量其他静态成员函数静态成员函数通常用于操作静态成员变量,或者作为工具函数提供与相关的功能。例如,在以下代码中,`PrintTotal`是一个静态成员函数,用于打印的总实例数: ```cpp class CRectangle { private: int w, h; static int nTotalArea; // 静态成员变量,记录总面积 static int nTotalNumber; // 静态成员变量,记录总对象数 public: CRectangle(int width = 0, int height = 0) : w(width), h(height) { nTotalArea += w * h; nTotalNumber++; } ~CRectangle() { nTotalArea -= w * h; nTotalNumber--; } static void PrintTotal() { std::cout << "Total number of rectangles: " << nTotalNumber << std::endl; std::cout << "Total area of rectangles: " << nTotalArea << std::endl; } }; int CRectangle::nTotalArea = 0; int CRectangle::nTotalNumber = 0; ``` 静态成员函数可以直接访问静态成员变量,但不能访问非静态成员变量,因为它们没有绑定到具体的对象实例。例如,以下代码会导致编译错误: ```cpp class A { private: int x; static int y; public: static void func() { x = 10; // 错误:静态成员函数不能访问非静态成员变量 y = 20; // 正确:静态成员函数可以访问静态成员变量 } }; ``` 静态成员函数可以通过名或对象调用。例如: ```cpp CRectangle::PrintTotal(); // 通过名调用 CRectangle rect; rect.PrintTotal(); // 通过对象调用 ``` --- ### 静态成员的访问权限 静态成员普通成员一样,可以具有`public`、`private``protected`访问权限。如果静态成员是私有的,则外无法直接访问,只能通过公共的静态成员函数访问。例如: ```cpp class A { private: static int _n; public: static int GetN() { return _n; } }; int A::_n = 0; int main() { std::cout << A::GetN() << std::endl; // 通过静态成员函数访问私有静态成员变量 return 0; } ``` --- ### 静态成员变量的初始化 对于静态成员变量,如果是`const`修饰的整型或枚举型,可以在内直接初始化。例如: ```cpp class MyClass { public: static const int MAX_SIZE = 100; // 内初始化 }; ``` 对于非`const`的静态成员变量,必须在外进行定义初始化。例如: ```cpp class MyClass { public: static int count; }; int MyClass::count = 0; // 外定义并初始化 ``` 如果静态成员变量是`const`且非整型,也需要在外定义: ```cpp class MyClass { public: static const double PI = 3.14159; // 内声明并初始化 }; const double MyClass::PI; // 外定义(可选) ``` --- ### 静态成员的应用场景 1. **资源管理**:静态成员常用于管理的共享资源,例如数据库连接池、线程池等。 2. **计数器**:静态成员变量可以用于记录的实例数量,帮助调试性能优化。 3. **单例模式**:静态成员函数常用于实现单例模式,确保一个只有一个实例存在。 4. **工具函数**:静态成员函数可以作为工具函数提供与相关的功能,而不需要创建对象。 例如,以下代码实现了一个简单的单例模式: ```cpp class Singleton { private: static Singleton* instance; Singleton() {} // 私有构造函数 public: static Singleton* getInstance() { if (!instance) { instance = new Singleton(); } return instance; } }; Singleton* Singleton::instance = nullptr; ``` --- ### 相关问题 1. C++中如何访问私有静态成员变量? 2. 静态成员函数能否访问非静态成员变量? 3. 静态成员变量的生命周期是什么? 4. 如何在C++中实现单例模式? 5. 静态成员函数能否被重载?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值