zoukankan      html  css  js  c++  java
  • C++:静态成员

    3.7.1 静态数据成员
    对象是类的一个实例,每个对象都具有自己的数据成员。例如,学生类张三或李四都具有自
    己的学号,姓名和平均成绩。在实际使用时,常常还需要一些其他的数据项,比如学生人数、
    总成绩、平均成绩。但是如果把这些数据项作为普通的数据成员来处理,将会产生错误。下
    面通过例子来说明:

     例3.28  静态数据成员的引例 
    
    #include<iostream>
    #include<string>
    using namespace std;
    class Student{
     public:
         Student(char* name1,char* stu_no1,float score1);//声明构造函数 
         ~Student();//声明析构函数 
         void show();
         void show_count_sum_ave();
     private:
         char* name;  //学生姓名 
         char* stu_no;//学生学号 
         float score;
         int count;  //定义普通数据成员count 
         float sum;  //定义普通数据成员sum 
         float ave;  //定义普通数据成员ave     
    };
    Student::Student(char* name1,char* stu_no1,float score1)
    {
      name = new char[strlen(name1)+1];//为学生姓名动态分配一个空间,并让name指向数组的首地址
      strcpy(name,name1);//首先name把name1指向的首地址复制过来,然后依次复制name1所指向的内容
      stu_no = new char[strlen(stu_no1)+1];
      strcpy(stu_no,stu_no1);
      score = score1; 
      count++;
      sum = sum+score;
      ave = sum/count;
    } 
    Student::~Student()
    {
      delete []name; //释放空间 
      delete []stu_no;//释放空间
      --count;
      sum = sum-score;
    } 
    void Student::show()
    {
      cout<<"姓名:"<<name<<endl;
      cout<<"学号:"<<stu_no<<endl;
      cout<<"成绩:"<<score<<endl; 
    } 
    void Student::show_count_sum_ave()
    {
      cout<<"学生人数:"<<count<<endl;
      cout<<"总成绩:"<<sum<<endl;
      cout<<"平均成绩:"<<ave<<endl; 
    }
    int main()
    {
     Student stu1("李明","1101",90.0);
     stu1.show();
     stu1.show_count_sum_ave();
     cout<<"------------------------"<<endl;
     
     Student stu2("王勇","1102",92.5);
     stu2.show();
     stu2.show_count_sum_ave();
     
     return 0;
    }
    /*
      运行结果发现:学生人数、总成绩、平均成绩都是错误的。
    
      其原因:一个学生对象的count、sum、ave仅仅属于这个学生对象,而不是所有学生对象
              所共享的,因此它们不能表示所有学生的人数、总成绩、平均成绩。
              
      解决办法:将count、sum、ave这个普通数据成员设为静态的数据成员,让所有的对象共享。
      
      格式为: static 数据类型 数据成员 
    */

    将上面的例子改为静态的数据成员来处理,如下....

    例3.29 静态数据成员的使用

    #include<iostream>
    #include<string>
    using namespace std;
    class Student{
     public:
         Student(char* name1,char* stu_no1,float score1);//声明构造函数 
         ~Student();//声明析构函数 
         void show();
         void show_count_sum_ave();
     private:
         char* name;  //学生姓名 
         char* stu_no;//学生学号 
         float score;
         static int count;  //定义静态数据成员count 
         static float sum;  //定义静态数据成员sum 
         static float ave;  //定义静态数据成员ave   
    };
    Student::Student(char* name1,char* stu_no1,float score1)
    {
      name = new char[strlen(name1)+1];//为学生姓名动态分配一个空间,并让name指向数组的首地址
      strcpy(name,name1);//首先name把name1指向的首地址复制过来,然后依次复制name1所指向的内容
      stu_no = new char[strlen(stu_no1)+1];
      strcpy(stu_no,stu_no1);
      score = score1; 
      count++;
      sum = sum+score;
      ave = sum/count;
    } 
    Student::~Student()
    {
      delete []name; //释放空间 
      delete []stu_no;//释放空间
      --count;
      sum = sum-score;
    } 
    void Student::show()
    {
      cout<<"姓名:"<<name<<endl;
      cout<<"学号:"<<stu_no<<endl;
      cout<<"成绩:"<<score<<endl; 
    } 
    void Student::show_count_sum_ave()
    {
      cout<<"学生人数:"<<count<<endl;
      cout<<"总成绩:"<<sum<<endl;
      cout<<"平均成绩:"<<ave<<endl; 
    }
    int Student::count=0;  //对静态数据成员count进行初始化 
    float Student::sum=0;  //对静态数据成员sum进行初始化
    float Student::ave=0;  //对静态数据成员ave进行初始化
    int main()
    {
     Student stu1("李明","1101",90.0);
     stu1.show();
     stu1.show_count_sum_ave();
     cout<<"------------------------"<<endl;
     
     Student stu2("王勇","1102",92.5);
     stu2.show();
     stu2.show_count_sum_ave();
     
     return 0;
    }

    说明:
    (1)静态数据成员的定义与普通数据成员相似,但前面要加上static关键字。
    static int count; //静态数据成员,用于统计学生人数
    static float score; //静态数据成员,用于统计学生成绩
    static float ave; //静态数据成员,用于统计学生平均分

    (2)静态数据成员的初始化与普通数据成员不同。静态数据成员初始化应在类外单独进行,
    而且应定义对象之前进行。一般在主函数main之前,类声明之后的特殊地带为它提供
    定义和初始化。初始化格式如下:

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

    int Student::count=0;
    int Student::sum=0;
    float Student::ave=0;

    注意:这时在数据成员的前面不要加static

    (3)静态数据成员属于类(准确的说,是属于类的对象的集合),而不像普通函数那样属于
    某一对象,因此可以使用"::"访问静态的数据成员。

    用类名访问静态数据成员的格式如下:

    类名::静态数据成员
    例如上面的Student::count、Student::sum、Student::ave

    (4)静态数据成员与静态变量一样,是在编译时创建并初始化。它在该类的任何对象被建立
    之前就存在。因此,共有的数据成员可以在对象被定义之前被访问。对象建立后,共有
    的静态数据成员也可以被对象进行访问。

    用对象访问静态数据成员的格式如下:

    对象.静态数据成员
    对象指针.静态数据成员

    例1:通过对象访问静态数据成员 

    #include<iostream>
    #include<string>
    using namespace std;
    class Student{
     public:
         Student(string name1,string stu_no1,float score1);//(char* name1,char* stu_no1,float score1) 
         ~Student();//声明析构函数 
         void show();
         void show_count_sum_ave();
     private:
         string name;  //学生姓名 
         string stu_no;//学生学号
    //     char* name;
    //     char* stu_no; 
         float score;
         static int count;  //定义静态数据成员count 
         static float sum;  //定义静态数据成员sum 
         static float ave;  //定义静态数据成员ave   
    };
    Student::Student(string name1,string stu_no1,float score1)//(char* name1,char* stu_no1,float score1)
    {
      //name = new char[strlen(name1)+1];//为学生姓名动态分配一个空间,并让name指向数组的首地址
    //  strcpy(name,name1);//首先name把name1指向的首地址复制过来,然后依次复制name1所指向的内容
    //  stu_no = new char[strlen(stu_no1)+1];
    //  strcpy(stu_no,stu_no1);
      score = score1; 
      name = name1;
      stu_no = stu_no1;
      count++;
      sum = sum+score;
      ave = sum/count;
    } 
    Student::~Student()
    {
      //delete []name; //释放空间 
    //  delete []stu_no;//释放空间
     // --count;
    //  sum = sum-score;
    } 
    void Student::show()
    {
      cout<<"姓名:"<<name<<endl;
      cout<<"学号:"<<stu_no<<endl;
      cout<<"成绩:"<<score<<endl; 
    } 
    void Student::show_count_sum_ave()
    {
      cout<<"学生人数:"<<count<<endl;
      cout<<"总成绩:"<<sum<<endl;
      cout<<"平均成绩:"<<ave<<endl; 
    }
    int Student::count=0;  //对静态数据成员count进行初始化 
    float Student::sum=0;  //对静态数据成员sum进行初始化
    float Student::ave=0;  //对静态数据成员ave进行初始化
    int main()
    {
     Student stu1("李明","1101",90.0);
     stu1.show();
     stu1.show_count_sum_ave();
     cout<<"------------------------"<<endl;
     
     Student stu2("王勇","1102",92.5);
     stu2.show();
     stu2.show_count_sum_ave();
     
     return 0;
    }

    例2:通过指针对象访问静态数据成员 

    #include<iostream>
    #include<string>
    using namespace std;
    class Student{
     public:
         Student(char* name1,char* stu_no1,float score1);//声明构造函数 
         ~Student();//声明析构函数 
         void show();
         void show_count_sum_ave();
     private:
         char* name;  //学生姓名 
         char* stu_no;//学生学号 
         float score;
         static int count;  //定义静态数据成员count 
         static float sum;  //定义静态数据成员sum 
         static float ave;  //定义静态数据成员ave   
    };
    Student::Student(char* name1,char* stu_no1,float score1)
    {
      name = new char[strlen(name1)+1];//为学生姓名动态分配一个空间,并让name指向数组的首地址
      strcpy(name,name1);//首先name把name1指向的首地址复制过来,然后依次复制name1所指向的内容
      stu_no = new char[strlen(stu_no1)+1];
      strcpy(stu_no,stu_no1);
      score = score1; 
      count++;
      sum = sum+score;
      ave = sum/count;
    } 
    Student::~Student()
    {
      delete []name; //释放空间 
      delete []stu_no;//释放空间
      --count;
      sum = sum-score;
    } 
    void Student::show()
    {
      cout<<"姓名:"<<name<<endl;
      cout<<"学号:"<<stu_no<<endl;
      cout<<"成绩:"<<score<<endl; 
    } 
    void Student::show_count_sum_ave()
    {
      cout<<"学生人数:"<<count<<endl;
      cout<<"总成绩:"<<sum<<endl;
      cout<<"平均成绩:"<<ave<<endl; 
    }
    int Student::count=0;  //对静态数据成员count进行初始化 
    float Student::sum=0;  //对静态数据成员sum进行初始化
    float Student::ave=0;  //对静态数据成员ave进行初始化
    int main()
    {
     Student stu1("李明","1101",90.0),*p1;
    // stu1.show();
    // stu1.show_count_sum_ave();
     p1 = &stu1;
     //p1->show();
     //p1->show_count_sum_ave();
     (*p1).show();
     (*p1).show_count_sum_ave();
     cout<<"------------------------"<<endl;
     
     Student stu2("王勇","1102",92.5),*p2;
     p2 = &stu2;
     //p2->show();
     //p2->show_count_sum_ave();
     (*p2).show();
     (*p2).show_count_sum_ave();
     
     return 0;
    }

    例3.30 公有静态数据成员的访问(在类外可以直接访问)
    (私有静态数据成员不能在类外直接访问,必须通过公有的成员函数访问。)

    #include<iostream>
    using namespace std;
    class Myclass{
      public:
        static int i;
        int get()
        {
          return i;
        }
    };
    int Myclass::i=0;
    int main()
    {
      Myclass::i=200;  //公有静态数据成员可通过对象进行访问 
      Myclass obj1,obj2;
      cout<<"obj1.i="<<obj1.get()<<endl;
      cout<<"obj2.i="<<obj2.get()<<endl;
      
      obj1.i=300;//公有静态数据成员通过对象进行访问并进行重赋值
      
      cout<<"obj1.i="<<obj1.get()<<endl;
      cout<<"obj2.i="<<obj2.get()<<endl;
      
      return 0; 
    }  
    /*
    
    运行结果为:  obj1.i=200
                obj2.i=200
                obj1.i=300
                obj2.i=300 
    解析:从本例中可以看出,由于静态数据成员只有一个值,所以不论用那个对象进行访问
          ,所得的结果是一样的。所以,从这个意义上讲,静态数据成员也是类的公共数据
          成员,是对象的共有数据项。
                      
    
    c++支持静态数据成员的一个重要原因是不必使用全局变量。因为全局变量违反了面向对象程序
    设计的封装性特点。静态数据成员主要作用于类的所有对象的公用的数据,如统计总数、平均数等....    
            
    */

    3.7.2 静态成员函数

    在类定义中,前面有static说明的成员函数称之为静态成员函数。静态成员函数属于整个
    类,是该类所有对象共享的成员函数,而不属于类中的某个对象。

    定义静态成员函数的格式如下:
    static 返回类型 静态数据成员函数(参数表);

    与静态数据成员类似,调用公有静态成员函数的一般格式有如下三种:
    1、类名.静态成员函数(实参表)
    2、对象.静态成员函数(实参表)
    3、对象指针->静态成员函数(实参表)

    //例3.31  静态成员函数访问静态数据成员。
    #include<iostream>
    using namespace std;
    class Small_cat{
      public:
          Small_cat(double w);            //声明构造函数 
          void display();                 //声明非静态成员函数 
          static void total_disp();          //声明非静态成员函数
      private:
          double weight;                  //定义普通数据成员,表示一只小猫的重量 
          static double total_weight;     //定义静态数据成员,用于累计小猫的重量 
          static double total_number;     //定义静态数据成员,用于累计小猫的数量 
    };      
    Small_cat::Small_cat(double w)        //定义构造函数 
    {
          weight = w;
          total_weight += w;              //累计小猫的重量 
          total_number++;                  //累加小猫的数量 
    } 
    void Small_cat::display()
    {
         cout<<"这只小猫的重量是:"<<weight<<"千克"<<endl;
    } 
    void Small_cat::total_disp()
     {
        cout<<total_number<<"只小猫的重量是:"<<total_weight<<"千克"<<endl; 
     }
     double Small_cat::total_weight=0;     //对私有的静态数据成员进行初始化 
     double Small_cat::total_number=0;     //对私有的静态数据成员进行初始化
    int main()
    {
     Small_cat::total_disp(); //对象创建之前,通过类名::调用静态成员函数
         
     Small_cat w1(0.5),w2(0.6),w3(0.4),*p;    //创建三个小猫对象并进行初始化,并另外定义一个指针p 
     w1.display();  //通过对象调用非静态成员函数 
     w2.display();
     w3.display();
     cout<<endl; 
     
     p = &w1;
     (*p).total_disp(); //通过指针调用静态成员函数 
     p->total_disp();
     cout<<endl;
     
     Small_cat::total_disp(); //通过类名::调用静态成员函数 
     w1.total_disp();//通过对象调用静态成员函数 
     w2.total_disp(); 
     w2.total_disp();
     
     return  0;
    } 

    对静态成员函数的使在作几点说明:
    1、一般情况下,静态函数成员主要用来访问静态数据成员。当它与静态数据成员一起使用
    时,达到了对同一类中对象之间共享数据的目的。

    2、私有静态成员函数不能做类外部的函数和对象访问。

    3、使用静态成员函数的一个原因是,可以用它在建立任何对象之前调用静态成员函数,以处理
    静态数据成员,这是普通成员函数不能实现的功能。

    例如: int main()
    {
          Small_cat::disp(); //可以在建立任何对象之前调用静态成员函数
          Small w1(0.5),w2(0.4),w3(0.6);
          .......
         return 0;
    }

    4、编译系统将静态成员函数限定为内部连接,也就是说,与现行文件相连接的其他文件
    中的同名函数不会与该函数发生冲突,维护了该函数使用的安全性,这是使用静态成员
    函数的另一个原因。

    5、静态成员函数是类的一部分,而不是对象的一部分。如果要在类外调用公有静态成员函数,
    使用格式是: 类名::静态成员函数

    例如上述中Small_cat::disp();

    当然如果定义了这个类的对象,也可以用对象调用静态成员函数

    如 w1.cat::disp();

    6、静态成员函数和非静态成员函数的区别是:非静态成员函数有this指针,而静态成员
    函数没有this指针。静态成员函数可以直接本类中的静态成员函数,因为静态数据成
    员同样是属于类的,可以直接访问。一般而言,静态成员函数不访问类中的非静态成
    员。
    例如:
    cout<<"一只小猫的重量是:<<weight<<"千克"<<endl;
    //不合法,weight是非静态数据成员
    cout<<"一只小猫的总重量是:<<total_weight<<"千克"<<endl;
    //合法,total_weight是静态数据成员

    若确实需要访问非静态数据成员,静态成员函数只能通过对象名(或对象指针、对象引用)
    访问该对象的非静态成员。如把display函数定义为静态成员函数时,可将对象的引用作为
    函数参数,将它定义为:
    static void display(Small_cat &w)
    {
            cout<<"这只小猫的重量是:"<<w.weight<<"千克"<<endl;
    }

    下面的例子给出了静态成员函数访问非静态数据成员的方法。

    3.32  静态成员函数访问非静态数据成员。                             
    */
    #include<iostream>
    using namespace std;
    class Small_cat
    {
       public:
         Small_cat(double w);                     //声明构造函数 
         static void display(Small_cat &);       //声明静态成员函数 
         static void total_disp();                //声明静态成员函数
       private:
         double weight;                           //普通数据成员,表示一只小猫的重量
         static double total_weight;              //静态数据成员,用来统计小猫的重量
         static double total_number;              //静态数据成员,用来统计小猫的数量 
    }; 
    Small_cat::Small_cat(double w)                           //定义构造函数 
    {                                              
         weight = w;                               
         total_weight += w;                       //累加小猫的重量
         total_number ++;                         //累加小猫的数量 
    }
    void Small_cat::display(Small_cat &w)         //定义静态成员函数,将对象的引用作为参数,
    {                                              //显示每只小猫的重量 
        cout<<"这只小猫的重量是:"<<w.weight<<"千克"<<endl;
    }
    void Small_cat::total_disp()                  //定义静态成员函数,输出小猫的总数量、总重量 
    {
        cout<<total_number<<"只小猫的重量是:";
        cout<<total_weight<<"千克"<<endl;
        cout<<endl;
    } 
    double Small_cat::total_weight=0;             //静态数据成员初始化 
    double Small_cat::total_number=0;             //静态数据成员初始化
    int main()
    {
       Small_cat::total_disp();          //在建立对象之前,调用静态成员函数,显示小猫的总数量、总重量 
        
       Small_cat w1(0.4),w2(0.5),w3(0.6);
       Small_cat::display(w1);                    //调用静态成员函数,显示第一只小猫的重量 
       Small_cat::display(w2);                    //调用静态成员函数,显示第二只小猫的重量
       Small_cat::display(w3);                    //调用静态成员函数,显示第三只小猫的重量
       
       Small_cat::total_disp();         // 在建立对象之后,调用静态成员函数,显示小猫的总数量、总重量
       
       return 0;
    }

     

  • 相关阅读:
    java 多线程2
    java 多线程1
    java Object
    java 模板
    03015_JSTL技术
    运维人员常用的Linux命令总结
    oracle的userenv和nls_lang详解
    Oracle字符集检查和修改
    sql语句中(+)的作用
    Oracle事务Transaction
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/4912206.html
Copyright © 2011-2022 走看看