C++_静态成员

静态成员

引入目的:实现一个类的不同对象之间数据和函数共享

谁共享:本类所有对象。

  • 静态数据成员
    • 用关键字static声明
    • 该类的所有对象维护该成员的同一个拷贝
    • 必须在类外定义和初始化,用(::)来指明所属的类。
  • 静态成员函数
    • 类外代码可以使用类名和作用域操作符来调用公有静态成员函数。
    • 静态成员函数只能引用属于该类的静态数据成员或静态成员函数。访问非静态数据成员,必须通过参数传递方式得到对象名,通过对象名访问。

1. 静态数据成员

为何需要静态数据成员?

例 静态数据成员的引例
#include<iostream.h>
#include<string.h>
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;
    float sum;
    float ave;
};
Student::Student(char *name1,char *stu_no1,float score1 )
{
    name=new char[strlen(name1)+1];
    strcpy(name,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<<"\n name: "<<name;
    cout<<"\n stu_no: "<<stu_no;
    cout<<"\n score: "<<score;
}
void Student::show_count_sum_ave()
{
    cout<<"\n count: "<<count;
    cout<<"\n sum: "<<sum;
    cout<<"\n ave: "<<ave;
}
void main()
{
    Student stu1("Liming","990201",90);
    stu1.show();
    stu1.show_count_sum_ave();
    Student stu2("Zhanghao","990202",85);
    stu2.show();
    stu2.show_count_sum_ave();
}

如何定义静态数据成员?

在一个类中,若将一个数据成员说明为static,这种成员称为静态数据成员。

静态数据成员特点?

  • 与一般的数据成员不同,无论建立多少个类的对象,都只有一个静态数据的拷贝。从而实现了同一个类的不同对象之间的数据共享
  • 它不因对象的建立而产生,也不因对象的析构而删除。它是类定义的一部分,所以使用静态数据成员不会破坏类的隐蔽性。
  • 在类的声明中只能声明静态数据成员的存在。由于类的声明是抽象的,静态数据成员的初始化需要在类的外部进行, 通过类名对它进行访问

静态数据成员初始化的格式

<数据类型> <类名> ∷ <静态数据成员名> = <值> ;

  • 初始化时不加该成员的访问权限控制符private,public等。
  • 初始化时使用作用域运算符来标明它所属的类,因此,静态数据成员是类的成员,而不是对象的成员。

引用静态数据成员时,采用如下格式:

<类名> ∷ <静态成员名>

  • 如果静态数据成员的访问权限允许的话(即public的成员),可在程序中,按上述格式来引用静态数据成员。
例3.15 静态数据成员的使用引例
#include<iostream.h>
#include<string.h>
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; // 静态数据成员,统计学生人数
    static float sum; // 静态数据成员,统计总成绩
    static float ave; // 静态数据成员,统计平均成绩
};
Student::Student(char *name1,char *stu_no1,float score1 )
{
    name=new char[strlen(name1)+1];
    strcpy(name,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<<"\n name: "<<name;
    cout<<"\n stu_no: "<<stu_no;
    cout<<"\n score: "<<score;
}
void Student::show_count_sum_ave()
{
    cout<<"\n count: "<<count; // 输出静态数据成员count
    cout<<"\n sum: "<<sum; // 输出静态数据成员sum
    cout<<"\n ave: "<<ave; // 输出静态数据成员ave
}
int Student::count=0; // 静态数员count初始化
float Student::sum=0.0; // 静态数员sum初始化
float Student::ave=0.0; // 静态数员ave初始化
void main()
{
    Student stu1("Liming","990201",90);
    stu1.show();
    stu1.show_count_sum_ave();
    Student stu2("Zhanghao","990202",85);
    stu2.show();
    stu2.show_count_sum_ave();
}

如何使用静态数据成员?

  • (1)静态数据成员的定义与一般数据成员相似,但前面要加上static关键词。
static 数据类型 数据成员名;
  • (2)静态数据成员的初始化与一般数据成员不同。
    • 初始化格式: 数据类型 类名::静态数据成员=值;
    • 初始化位置:定义对象之前,一般在类定义后,main()前进行。
  • (3) 访问方式(只能访问公有静态数据成员)
    • 可用类名访问: 类名::静态数据成员
    • 也可用对象访问:
      • 对象名.静态数据成员
      • 对象指针->静态数据成员
【例3.16】 公有静态数据成员的访问
#include<iostream.h>
class myclass{
public:
    static int i;
    int geti()
    { return i;}
};
int myclass∷i=0; // 初始化,不必在前面加static
main()
{
    myclass∷i=200;
    myclass ob1,ob2;
    cout<<"ob1.i="<<ob1.geti()<<endl;
    cout<<"ob2.i="<<ob2.geti()<<endl;
    ob1.i=300; // 对象进行访问
    cout<<"ob1.i="<<ob1.geti()<<endl;
    cout<<"ob2.i="<<ob2.geti()<<endl;
    return 0;
}
  • (4) 私有静态数据成员不能被类外部函数访问,也不能用对象进行访问。

  • (5) 支持静态数据成员的一个主要原因是可以不必使用全局变量。静态数据成员的主要用途是定义类的各个对象所公用的数据。

【例3.17】 静态数据成员和一般数据成员的不同
#include<iostream.h>
class Student{
public:
    Student() // 构造函数
    {
        ++count; // 每创建一个学生对象,学生数加1
        StudentNo=count; // 给当前学生的学号赋值
    }
    void print() // 成员函数,显示学生的学号和当前学生数
    {
        cout<<"Student"<<StudentNo<<" ";
        cout<<"count="<<count<<endl;
    }
private:
    static int count; // 静态数据成员count,统计学生的总数
    int StudentNo; // 普通数据成员,用于表示每个学生的学号
};
int Student::count=0;
main()
{
    Student Student1;
    Student1.print();
    cout<<"-----------\n";
    Student Student2;
    Student1.print();
    Student2.print();
    cout<<"-----------\n";
    Student Student3;
    Student1.print();
    Student2.print();
    Student3.print();
    cout<<"-----------\n";
    Student Student4;
    Student1.print();
    Student2.print();
    Student3.print();
    Student4.print();
    return 0;
}

执行结果为:

Student1 count=1
------------
Student1 count=2
Student2 count=2
------------
Student1 count=3
Student2 count=3
Student3 count=3
------------
Student1 count=4
Student2 count=4
Student3 count=4
Student4 count=4

2. 静态成员函数

  • 可以通过定义和使用静态成员函数来访问静态数据成员。
  • 所谓静态成员函数就是使用static关键字声明函数成员。同静态数据成员一样,静态成员函数也属整个类, 由同一个类的所有对象共同维护,为这些对象所共享。
  • 静态成员函数作为成员函数,它的访问属性可以受到类的严格控制。对公有静态成员函数,可以通过类名或对象名来调用;而一般的非静态公有成员函数只能通过对象名来调用。
  • 静态成员函数可以直接访问该类的静态数据成员和函数成员;而访问非静态数据成员,必须通过参数传递方式得到对象名,然后通过对象名来访问。

定义静态成员函数的格式如下

static 返回类型 静态成员函数名(参数表);

使用目的: 在对象建立之前处理静态数据成员或全局变量

使用公有静态成员函数的一般格式

与静态数据成员类似,使用公有静态成员函数的一般格式有如下几种:

  • 类名::静态成员函数名(实参表)
  • 对象. 静态成员函数名(实参表)
  • 对象指针->静态成员函数名(实参表)
例3.18静态成员函数来访问静态数据成员
#include<iostream.h>
#include<string.h>
class Student {
private:
    char *name;
    char *stu_no;
    float score;
    static int count;
    static float sum;
public:
    Student(char *name1,char *stu_no1,float score1);
    ~Student();
    void show();
    static void show_count_sum();
};
Student::Student(char *name1,char *stu_no1,float score1 )
{
    name=new char[strlen(name1)+1];
    strcpy(name,name1);
    stu_no=new char[strlen(stu_no1)+1];
    strcpy(stu_no,stu_no1);
    score=score1;
    ++count; // 累加学生人数
    sum=sum+score; // 累加总成绩
}
Student::~Student()
{
    delete []name;
    delete []stu_no;
    --count;
    sum=sum-score;
}
void Student::show()
{
    cout<<"\n name: "<<name;
    cout<<"\n stu_no: "<<stu_no;
    cout<<"\n score: "<<score;
}
void Student::show_count_sum() // 静态成员函数
{
    cout<<"\n count: "<<count; // 输出静态数据成员
    cout<<"\n sum: "<<sum; // 输出静态数据成员
}
int Student::count=0; // 静态数据成员初始化
float Student::sum=0.0; // 静态数据成员初始化void main()
{
    Student stu1("Liming","990201",90);
    stu1.show();
    Student::show_count_sum(); // 使用类名访问静态成员函数
    Student stu2("Zhanghao","990202",85);
    stu2.show();
    stu2.show_count_sum(); // 使用对象stu2访问静态成员函数
}

使用静态成员函数时须注意

  • (1) 静态成员函数可以定义成内嵌的,也可以在类外定义,在类外定义时不能用static前缀。
  • (2) 静态成员函数主要用来访问全局变量或同一个类中的静态数据成员。特别是,当它与静态数据成员一起使用时,达到了对同一个类中对象之间共享数据进行维护的目的。
  • (3) 私有静态成员函数不能被类外部函数和对象访问。
  • (4) 使用静态成员函数的一个原因是,可以用它在建立任何对象之前处理静态数据成员。这是普通成员函数不能实现的。
  • (5) 静态成员函数中没有指针this,所以静态成员函数不访问类中的非静态数据成员,若确实需要则只能通过对象名(作为参数)访问。
【例3.19】 静态成员函数访问非静态数据成员
#include<iostream.h>
class small_cat {
public:
    small_cat(double w)
    {
        weight=w;
        total_weight+=w;
        total_number++;
    }
    static void display(small_cat& w)//访问非静态成员
    { cout<<"The small_cat weights "<<w.weight<<" kg\n";}
    static void total_disp() //访问静态成员
    {
        cout<<total_number<<" small_cat total_weight ";
        cout<<total_weight<<"kg "<<endl;
    }
private:
    double weight;
    static double total_weight;
    static double total_number;
};
double small_cat∷total_weight=0;
double small_cat∷total_number=0;
int main()
{
    small_cat w1(0.9), w2(0.8), w3(0.7);
    small_cat∷display(w1);
    small_cat∷display(w2);
    small_cat∷display(w3);
    small_cat∷total_disp();
    return 0;
}

通过普通指针访问静态成员

例3.20 通过指针访问类的静态数据成员
#include<iostream.h>
class myclass {
public:
    myclass() // 构造函数,每定义一个对象, 静态数据成员i加1
    { ++i; }
    static int i; // 声明静态数据成员i
};
int myclass::i=0; // 静态数据成员i初始化,不必在前面加static
main()
{
    int *count=&myclass::i;
    myclass ob1,ob2,ob3,ob4;
    cout<<“ myclass::i= ”<<*count<<endl;
    return 0;
}
【例3.21】 通过指针访问类的静态成员函数
#include<iostream.h>
class myclass {
public:
    myclass()
    { ++i; }
    static int geti()
    { return i; }
private:
    static int i;
};
int myclass::i=0;
main()
{
    int (*get)()=myclass::geti;
    myclass ob1,ob2,ob3;
    cout<<"myclass∷i="<<(*get)()<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/whale90830/p/10538917.html