static静态成员

 只用于本文件的成员函数要全部声明为static;

一、静态成员

在类定义中,其成员(成员变量和成员函数)可以用关键字static声明为静态的,称为静态成员。
  1. 静态成员函数只能访问静态成员函数和静态成员变量,没有this指针;
  2. 静态成员是整个类共有的,通过对象名和类名都可以访问,不计入类的字节数;
  3. 静态成员变量,属于某个类,所有对象共享,在编译阶段分配空间,存储于全局区,即对象还没有创建时,就已经分配空间;
  4. 静态成员变量必须在类中声明,类外定义。static成员属于某个类,不属于某个对象。静态成员变量必须在类声明的外部初始化;
  5. 静态数据成员不属于某个对象,在为对象分配空间中不包括静态成员所占空间。
#include<iostream>
using namespace std;
void Static()
{
    static int n = 1;
    n *= 2;
    cout<<"静态变量:"<<n<<endl;
}
void Auto()
{
    int n = 1;
    n *= 2;
    cout<<"普通变量:"<<n<<endl;
}
int main()
{
    Static();  //输出:静态变量:2
    Static();  //输出:静态变量:4
    Static();  //输出:静态变量:8
    Static();  //输出:静态变量:16
    Auto();  //输出:普通变量:2
    Auto();  //输出:普通变量:2
    Auto();  //输出:普通变量:2
    Auto();  //输出:普通变量:2
    return 0;
}

二、静态数据成员和普通数据成员的共同点 

静态数据成员和普通数据成员一样遵从public,protected,private访问规则;

三、为什么要使用静态数据成员

 每个对象都有自己都有的数据成员,不同对象如何共享数据?
    全局变量:谁都可以访问,不安全
    静态数据成员:可以实现数据共享,该类的所有对象都共享这块静态存储空间它不属于某一个对象,它与整个程序的生命周期相同,即使某个对象消亡了,静态数据成员还存在,没有改变

四、静态数据成员的初始化

static 数据类型  成员变量名;

 数据类型  类名::静态成员变量=初始值;

不能在类中对非const静态变量进行定义并初始化,而是只能声明;即类中声明,类外初始化(分配内存)。

  • 为什么不能在类中对非const静态变量进行定义并初始化?

我们不对静态成员变量进行与普通成员变量不同的处理,而是一样能在类的声明里事先定义并初始化好静态成员变量(也就是声明时给定一个初始值,等真正实例化一个对象时便用事先给定的初始值初始化这个变量):static int sti_data = 1;,这意味着,每个我们实例化的类对象,都存在一个分配给静态成员变量的内存,这将导致在内存中存在多个同名的静态变量,这与静态变量的唯一性矛盾,必然编译不通过。

  • 为什么const静态变量能够在类内直接定义?

因为static const 成员变量会被编译器优化,为编译期常量,编译器不会为其分配内存,更像是宏定义那样,在编译期时,在使用它的地方,用它的值替换它,这一点可以通过代码看到,若我们在类中定义一个static const 成员变量,我们可以打印出它的值,却不能打印出它的地址,因为编译器并没有给它分配内存。

  • 函数里面的静态变量可以初始化?

每个的函数,无论是否静态,是否是成员函数还是普通函数,程序在编译时,会给每个函数分配内存,同时一个函数在程序里只有一份内存,这与类在实例化一个对象时才分配内存是有本质上的区别的。这时,对于函数的静态变量而言,只需要把静态变量的内存分配到静态区就能做到在程序的生命周期里不随着函数的调用而被构造或者销毁。
 

#include<iostream>
using namespace std;
class Data
{
    public:
        int n;
        static int m;    //静态成员变量 类内声明,静态数据成员不能直接初始化,此处不能初始化
};
int Data::m=0;        //类外初始化,::表示m是属于Data这个类的 

         
int main()
{
    Data d1,d2;
    return 0;
}

// d1.n 与 d2.n 是两个不同的变量

// d1.m 与 d2.m 是同一个变量

五、静态成员的访问方式

类对象名.静态数据成员名

类的类型名::静态数据成员名

静态数据成员也遵从public,protected,private访问规则

//访问静态数据成员
#include<iostream>
using namespace std;
class A
{
	public:
		static int i;
};
int A::i=5;//::表示i是属于A这个类的 
int main()
{
	A a;
	cout<<A::i<<endl;//通过类名加域作用符直接访问 
	cout<<a.i<<endl;//通过对象访问 
	A * a1=&a;
	cout<<a1->i; //通过对象指针访问数据成员 
	return 0; 
 } 
//访问静态成员函数 
#include <iostream>
using namespace std;
class Box{
    public:
    	static int c;
    	int a,b;
    	Box(int x,int y){
    		a=x;b=y;
		}
        static void fun(){
        	cout<<c<<endl;
        	cout<<"static fun----"<<endl;	
		}      
};
int Box::c=8;
int main(){
    Box box(2,3);
    Box::fun();//使用作用域运算符直接访问静态成员 
    box.fun();//通过对象.引用名 
    Box * box2=&box; 
	box2->fun(); //通过类Box对象的指针 
    return 0;
}

六、静态成员函数

  • 在对象没有创建前,即可通过类名调用。主要用于管理静态数据成员。

static成员函数只能访问static成员,包括数据成员和成员函数;

非static成员函数既可以访问static数据成员,也可以访问非static数据成员;

 static  返回值类型  函数名(参数表);

 //声明要写static,定义不用写static

静态成员函数可以直接引用私有的静态数据成员(不用加类名或者对象名,因为静态数据是共有的,任何对象的该成员是一个值);

#include<iostream>
using namespace std;
class Student
{
    int id;
    float score;
    static float sum;    //静态成员变量声明,总分
    static int count;    //计数
    
    public:
        Student(int i,int s):id(i),score(s)        //定义构造函数
        {
            count++;
        }
        void total();                //总分    
        static float average(); //平均数     //静态成员函数的声明
};
        
float Student::sum = 0;        //静态成员变量的初始化
int Student::count = 0;

void Student::total()
{
    sum += score;
}

float Student::average()        //静态成员函数
{
    if(count)
    {
        return sum/count;
    }
}

int main()
{
    Student stu[3] = {Student(1,10) , Student(2,20) , Student(3,30)};
    for(int i=0;i<3;i++)
    {
        stu[i].total();
    }
    cout<<"平均分是:"<<Student::average();        //不需要用对象,因为这是共有的
    return 0;
}

七、静态变量和普通变量区别

  • 全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对其初始化。
  • 普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。
  • 静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。
  • 在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。

 八、静态函数和普通函数区别

  • 静态函数只能在声明它的文件中可见,其他文件不能引用该函数;
  • 不同的文件可以使用相同名字的静态函数,互不影响;
  • 非静态函数可以在另一个文件中直接引用,甚至不必使用extern声明;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值