static在C语言和C++中的区别 | 十分详细,一文彻底解决static

static在C语言中用法:

1)全局量被静态关键字修饰只在本文件中有效,仍存储在静态区,生命周期没变。

2)函数被静态关键字修饰只在本文件中有效

3)在函数中局部变量用静态关键字定义,生命周期存在于整个程序中,但变量只能在函数中访问,且此只能创建初始化一份

4)static 修饰变量还有一特点,当变量未初始化时,默认初始化为 0。这是因为在静态存储区,所有内存都被默认置为 0,有时这一特点可减少工作量。

static在C++中用法:

1)类的静态成员变量

被static修饰的成员变量和成员方法独立于该类的任何对象。 也就是说,它不依赖类特定的实例,被类的所有实例共享。 只要这个类被加载,编译器就能根据类名在运行时数据区内找到他们。 按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。 

对象的内存中包含了成员变量,不同的对象占用不同的内存,有不同的成员数据并共用成员函数方法,这使得不同对象的成员变量相互独立,它们的值不受其他对象的影响。例如有两个相同类型的对象 a、b,它们都有一个成员变量 m_name,那么修改 a.m_name 的值不会影响 b.m_name 的值。

可是有时候我们希望在多个对象之间共享数据,对象 a 改变了某份数据后对象 b 可以检测到。共享数据的典型使用场景是计数,以前面的 Student 类为例,如果我们想知道班级中共有多少名学生,就可以设置一份共享的变量,每次创建对象时让该变量加 1。


在C++中,我们可以使用静态成员变量来实现多个对象共享数据的目标。
静态成员变量是一种特殊的成员变量,它被关键字static修饰,例如:
class Student{
public:
    Student(char *name, int age, float score);
    void show();
public:
    static int m_total;  //静态成员变量 m_total,用来统计学生的人数
private:
    char *m_name;
    int m_age;
    float m_score;
};
static 成员变量属于类,不属于某个具体的对象,即使创建多个对象,
也只为 m_total 分配一份内存,所有对象使用的都是这份内存中的数据。
当某个对象修改了 m_total,也会影响到其他对象。

 static 成员变量必须在类声明的外部初始化,具体形式为:

type class::name = value;

type 是变量的类型,class 是类名,name 是变量名,value 是初始值。将上面的 m_total 初始化:

int Student::m_total = 0;
静态成员变量在初始化时不能再加 static,但必须要有数据类型。
被 private、protected、public 修饰的静态成员变量都可以用这种方式初始化。

 注意:static 成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,而是在(类外)初始化时分配。反过来说,没有在类外初始化的 static 成员变量不能使用。

成员变量既可以通过对象来访问,也可以通过类来访问。请看下面的例子:

//通过类访问 static 成员变量
Student::m_total = 10;
//通过对象访问 static 成员变量
Student stu("小明", 15, 92.5f);
stu.m_total = 20;
//通过对象指针访问 static 成员变量
Student *pstu = new Student("李华", 16, 96);
pstu -> m_total = 20;
2)类的静态成员函数

在类中,static 除了可以声明静态成员变量,还可以声明静态成员函数。

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

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

class Object
{
private:
    int value;
    static Object objx;
public:
    Object(int x = 0) :value(x) { cout << "create object" << endl; }
    ~Object() { cout << "destroy object" << endl; }

    //void SetValue(Object* const this,int x=0)
    void SetValue(int x = 0) { value = x; }//隐式添加this

    //int GetValue(const Object* const this)
    int GetValue() const { return value; }//隐式添加this

    static Object& GetObject();//static修饰则函数没有this指针
};

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

解释:普通成员变量占用对象的内存,静态成员函数没有 this 指针,不知道指向哪个对象,无法访问对象的成员变量,也就是说静态成员函数不能访问普通成员变量,只能访问静态成员变量。 普通成员函数必须通过对象才能调用,而静态成员函数没有 this 指针,无法在函数体内部访问某个对象,所以不能调用普通成员函数,只能调用静态成员函数。

为什么要有this指针?

1.节省空间

2.所有类对象公用成员函数方法,数据都是私有的,用this指针区分不同对象调用成员函数。

#include <iostream>
using namespace std;

class Student {
public:
    Student(const char *name, int age, float score);
    void show();
public:  //声明静态成员函数
    static int getTotal();
    static float getPoints();
private:
    static int m_total;  //总人数
    static float m_points;  //总成绩
private:
    const char *m_name;
    int m_age;
    float m_score;
};

int Student::m_total = 0;//静态成员必须在类外初始化
float Student::m_points = 0.0;//静态成员必须在类外初始化

Student::Student(const char *name, int age, float score) : m_name(name), m_age(age), m_score(score) {
    m_total++;
    m_points += score;
}
void Student::show() {
    cout << m_name << "的年龄是" << m_age << ",成绩是" << m_score << endl;
}
//定义静态成员函数
int Student::getTotal() {
    return m_total;
}
float Student::getPoints() {
    return m_points;
}

int main() {
    (new Student("小明", 15, 90.6))->show();
    (new Student("李磊", 16, 80.5))->show();
    (new Student("张华", 16, 99.0))->show();
    (new Student("王康", 14, 60.8))->show();
    int total = Student::getTotal();
    float points = Student::getPoints();
    cout << "当前共有" << total << "名学生,总成绩是" << points << ",平均分是" << points / total << endl;
    return 0;
}

总人数 m_total 和总成绩 m_points 由各个对象累加得到,必须声明为 static 才能共享;getTotal()、getPoints() 分别用来获取总人数和总成绩,为了访问 static 成员变量,我们将这两个函数也声明为 static。

在C++中,静态成员函数的主要目的是访问静态成员。getTotal()、getPoints() 当然也可以声明为普通成员函数,但是它们都只对静态成员进行操作,加上 static 语义更加明确。

和静态成员变量类似,静态成员函数在声明时要加 static,在定义时不能加 static。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宠宠熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值