C++中的静态成员变量和静态成员函数

 在不用全局变量的情况下,同类的多个对象之间实现数据共享可以考虑使用静态成员变量。

一、静态成员变量

    -静态成员变量属于整个类所有
    -静态成员变量的生命期不依赖于任何对象,为程序的生命周期
    -可以通过类名直接访问公有静态成员变量
    -所有对象共享类的静态成员变量
    -可以通过对象名访问公有静态成员变量
    -静态成员变量需要在类外单独分配空间
    -静态成员变量在程序内部位于全局数据区 (Type className::VarName = value)

静态成员变量是一种特殊的成员变量,类体中的数据成员声明时前面加上关键字static,即成为该类的静态数据成员,即静态成员变量。静态成员变量实际上就是类域中的全局变量,必须初始化,且只能在类体外。初始化时不受private和protected访问限制。

class Student{
private:
    char *name;
    int age;
    float score;
    static int num; //将num声明为静态成员变量
public:
    Student(char *, int, float);
    void say();
};
int Student::num = 0; //静态成员变量的初始化同时赋值,初始化时可不加static
Student::num = 0;  //通过类来访问
Student stu;   //通过对象来访问,与通过类访问等效
stu.num = 0;

Student::Student(char *name, int age, float score)
{
    this->name = name;
    this->age = age;
    this->score = score;
    num++;
}

void Student::say()
{
    //在普通成员函数中可以访问静态成员变量
    cout<<name<<"的年龄是 "<<age<<",成绩是 "<<score<<"(当前共"<<num<<"名学生)"<<endl;  
}

int main()
{
    //使用匿名对象
    //匿名对象就是没有明确的给出名字的对象,是对象的一种简写形式。 
    //一般匿名对象只使用一次,而且匿名对象只在堆内存中开辟空间,而不存在栈内存的引用。
    (new Student("小明", 15, 90)).say();
    (new Student("李磊", 16, 80)).say();
    (new Student("张华", 16, 99)).say();
    (new Student("王康", 14, 60)).say();
    return 0;
}

//运行结果:
//小明的年龄是 15,成绩是 90(当前共1名学生)
//李磊的年龄是 16,成绩是 80(当前共2名学生)
//张华的年龄是 16,成绩是 99(当前共3名学生)
//王康的年龄是 14,成绩是 60(当前共4名学生)

上面的代码申明了静态成员变量num。

静态成员变量属于类,不属于某个具体的对象。如上面的代码,即使创建多个对象,也只为num分配一份内存,所有对象使用的是这份内存中的数据,当某个对象修改了num,也会影响到其他的对象。static成员变量不占用对象内存,在所有对象外开辟内存,不创建对象也可以访问。

static成员变量和普通static变量一样,编译时在静态数据区分配内存,到程序结束时才释放。这就意味着static成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。

static成员变量初始化不赋值会被默认初始化,一般是 0静态数据区的变量都有默认的初始值,而动态数据区(堆区、栈区)的变量默认是垃圾值。

class base
{ 
public:
    static int num;   //声明 
}; 
int base::num=0;  //静态成员变量的真正定义 

class derived:public base{ };    //继承派生操作

void main() 
{ 
    base a; 
    derived b; 
    a.num++; 
    cout<<"base class static data number num is"<<a.num<<endl; 
    b.num++; 
    cout<<"derived class static data number num is"<<b.num<<endl; 
}// 结果为1,2;可见派生类与基类共用一个静态数据成员

根据上述代码,显而易见,静态成员变量可以被自己所在类派生类的对象共享

class base{ 
public: 
    static int staticVar; 
    int _var; 
    void foo1(int i = staticVar);   //正确,staticVar为静态数据成员 
    void foo2(int i = _var);    //错误,_var为普通数据成员 
}; 

上述代码说明了:静态成员变量可以成为成员函数的可选参数,而普通成员变量不可以。

普通成员变量如果在成员函数被调用前没有被初始化,此时编译器无法确认函数参数的默认值是多少。

class base{ 
public: 
    static base _1object;//正确,静态数据成员 
    base _2object;//错误 
    base *pObject;//正确,指针 
    base &mObject;//正确,引用 
}; 

上述代码说明:静态成员变量的类型可以是所属类的类型,但是普通成员变量不行。普通成员只能声明为所属类类型的指针或引用。

二、静态成员函数

    -静态成员函数是类的一个特殊的成员函数
    -
静态成员函数属于整个类所有,没有this指针
    -
静态成员函数只能直接访问静态成员变量和静态成员函数
    -可以通过类名直接访问类的公有静态成员函数
    -可以通过对象名访问类的公有静态成员函数
    -定义静态成员函数,直接使用static关键字修饰即可

注意下面几点:

调用一个对象的非静态成员函数时,系统会把当前对象的起始地址赋给 this 指针。而静态成员函数并不属于某一对象,它与任何对象都无关,因此静态成员函数没有 this 指针

静态成员函数与非静态成员函数的根本区别是:有无this指针。由此决定了静态成员函数不能访问本类中的非静态成员。

如果类的成员函数想作为回调函数来使用,一般情况下只能将它定义为静态成员才行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hiOoo.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值