对象和类——类的静态成员

本文深入探讨了C++中静态成员变量与静态成员函数的概念、使用方法及其限制条件,并通过实例代码展示了它们的具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文参照于狄泰软件学院,唐佐林老师的——《C++深度剖析教程》

有些时候,我们需要一些类成员与类本身直接相关。而不是与类的各个对象保持关联。
也就是:我们每创建一个类对象,类成员变量就会多出一份,各个对象间的成员变量不能共享,是各自独立的变量。
但是,我们有些时候需要定义一个成员变量,使其在各个类对象之间关联起来。当这个变量发生改变时,所有对象中都能使用新值。

思路:
能在所有对象中共用的,也就是声明周期是整个程序运行期,存放在静态存储区的。那么能实现功能的就只有:全局变量和静态成员变量了。从安全性的角度来看,静态成员变量会更加适用。

类的静态成员变量

1. 静态成员变量属于整个类所有
因为静态成员变量并不属于某个对象,所以我们可以通过类名来直接访问公有静态成员变量。也可以通过对象名访问公有成员变量。

2. 静态成员变量的特性与全局变量相同
静态成员变量实际在类外单独分配空间,在程序内部存储于全局数据区;静态成员变量的生命期为程序运行期,不依赖于任何对象。

3. 在定义时直接通过static关键字修饰
静态成员变量需要在类外进行赋值,不能在构造函数中进行赋值。
语法规则:Type ClassName::VarName = value;

示例代码:静态成员变量的使用

#include <iostream>

using namespace std;

class Test
{
private:
    static int cCount;  
public:
    Test()
    {
        cCount++;
    }  
    ~Test()
    {
        cCount--;
    }

    int getCount()
    {
        return cCount;
    }
};

int Test::cCount = 0;

int main()
{  
    Test t1, t2;

    cout << "obj number is " << t1.getCount() << endl;

    Test* pt = new Test();

    cout << "obj number is " << pt->getCount() << endl;

    delete pt;

    cout << "obj number is " << t1.getCount() << endl;

    //  cout << Test::cCount << endl;  //Error 
    return 0;
} 

输出结果:
obj number is 2
obj number is 3
obj number is 2

分析:
1. int Test::cCount = 0; 这语句将静态成员初始化为0。但是静态成员变量是在类外进行初始化的。为什么静态成员变量一定要类外进行声明呢?
这是因为声明描述了如何分配内存,但并不分配内存。这是因为静态类成员是单独存储的,而不是对象的组成部分,所以不是在创建类对象时被定义的,因此不能在类中进行初始化,否则每创建一个对象都会初始化静态成员了。

  1. cout << Test::cCount << endl; //Error 刚才我们不是说可以使用类名直接调用静态成员变量吗?为什么会错误呢?
    这是因为我们在类中将静态成员变量定义为私有的,我们无法通过类名直接访问它,只能通过调用getCount()函数。
    虽然我们可以通过吧cCount转为公有成员,然后通过类名直接访问。但是安全性却不能保障了,因为程序中可以随意修改公有静态成员变量的值了。

由此可见:正因为这个程序无法直接使用类名访问静态成员变量,导致了在没有对象时,我们无法访问getCount() 函数。也就是我们无法判断目前程序中对象数量是否为0。

问题:如何解决无法判断对象数量为0的情况?

类的静态成员函数

实际上,static关键字也可以用于函数上面,使用方法和静态成员变量一致。

静态成员函数是类中的特殊的成员函数。属于属于整个类所有。
因为静态成员函数并不属于某个对象,所以我们可以通过类名来直接访问公有静态成员函数。也可以通过对象名访问公有成员函数。

示例代码:静态成员函数的使用

#include <iostream>

using namespace std;

class Test
{
private:
    static int cCount;  
public:
    Test()
    {
        cCount++;
    }

    ~Test()
    {
        cCount--;
}

    static int getCount()
    {
        return cCount;
    }
};

int Test::cCount = 0;

int main()
{

    cout << "obj number is " << Test::getCount() << endl;

    Test t1;

    cout << "obj number is " << t1.getCount() << endl;

    return 0;
} 

输出结果:
obj number is 0
obj number is 1

类的静态成员函数不能访问非静态成员变量

思考:类的静态成员函数和类的成员函数有什么区别?

示例代码:静态成员函数与普通成员函数

#include <iostream>

 using namespace std;

 class Point
 {
 public:
     Point()
     {
                m_x = 10;
     }

     static void output()
     {
         cout << "m_x = " << m_x << endl;
     }

     void print()
     {
                cout << "ci = " << ci << endl; 
     }
 private:
     int m_x;
     static int ci;
 };

int Point::ci = 5;

int main()
{
     Point pt;
     //pt.output(); //Error

     pt.print();

     return 0;
}

得出结论:
1. 静态成员函数中不能调用非静态成员函数。
2. 非静态成员函数中可以调用静态成员。

思考:为什么静态成员函数中不能调用非静态成员函数?

我们知道,静态成员函数是属于类的,可以通过类名直接访问,而不需具体的对象。那么如果有两个对象,而这两个对象的成员变量不相同。而这个类的静态成员函数用于访问类中的成员,那么我们在程序中到底是访问哪个对象的成员变量呢?
所以,静态成员函数不能直接访问非静态成员变量(函数)。

问题:我们知道静态成员函数和普通成员函数都是所有对象共享的。那么为什么普通成员函数就能够区别各个对象间的成员变量不同呢?

因为静态成员函数没有隐藏的this指针。
既然没有this指针,我们可以吧对象直接传进静态成员函数中嘛。然后就可以访问特定对象的非静态成员变量了。

通过函数参数访问类的非静态成员变量

示例代码:见招拆招

#include <stdio.h>
 class Point
 {
 public:
     Point()
     {
        m_x = 10;
     }
     void init()
     {
     }
     static void output(Point* p)
     {
         printf("m_x = %d\n", p->m_x);
     }
 private:
     int m_x;
 };
int main()
{
     Point pt;
     pt.output(&pt);

     return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值