成员函数:C\C++语言19|静态成员(对象共享数据成

 2021-07-06 23:16    77  

类中可以包含静态数据成员和静态函数成员成员函数,统称为静态成员。默认情况下,静态成员的作用域是类范围内且是外部链接的。静态成员在内存中只有一个副本,不是类对象的一部分,而是独立的对象。因此,静态数据成员的声明不是定义,声明在类作用域内完成,而定义在文件作用域内完成。

不管这个类有多少个对象成员函数,静态数据成员都只有一份拷贝。静态数据成员一般用来保存整个类所有对象共享的信息。

1 静态成员变量假设类SavingAccount专门用于存放存款帐户成员函数,它包括存户的姓名、地址、存款额、利率等成员变量:

class SavingAccount{char m_name[20]; //存户姓名char m_addr[60]; //存户地址double m_total; //存款额double m_rate; //利率…};这家银行采用浮动利率,每个帐户的利息根据当天的挂牌利率计算。这时候如果m_rate就不适合成为每个帐号一个资料,否则每天一开市,光把所有帐户内容调出来,修改m_rate的值,就花掉不少时间。m_rate应该独立于各对象之外,成为独一无二的资料。怎样实现呢?就是声明为各对象共享的数据,使用关键字static。

对于静态成员数据:

1)在编译阶段就分配空间,对象还没有创建;

2)必须在类中声明,在类外初始化(或定义)。

由于静态数据成员要在类声明与定义时实际分配空间,因此不能在类声明中进行初始化。静态数据成员初始化在类的外部进行,且与一般数据成员初始化不同,它的格式如下:

<数据类型><类名>::<静态数据成员名>=<值>3)归同一个类的所有对象所有,共享同一个静态变量。在为对象分配的空间中不包含静态成员所占空间。

4)有权限限制:private静态变量和 public静态变量。

private静态变量;在类(print类)外不能访问和操作。

类外访问:print::a;//erro 类外操作:print::a = 6;//erropublic静态变量;在类(print类)外可以访问和操作。

类外访问:print::a;//yes 类外操作:print::a = 6;//yes5)const 静态成员变量

const static int a = 8;定义静态变量 const 静态成员变量时,最好在类的内部初始化。

static 成员变量不属于对象的一部份,而是类别的一部份,所以程序可以在还没有诞生任何对象的时候就处理此种成员变量。但首先你必须初始化它。不要把static 成员变量的初始化动作安排在类别的构造式中,因为构造式可能一再被调用,而变量的初值却只应该设定一次。也不要把初始化动作安排在头文件中,因为它可能会被包含许多地方,因此也就可能被执行许多次。你应该在实作档中且类别以外的任何位置设定其初值。例如在main 之中,或全域函数中,或任何函数之外:

double SavingAccount::m_rate = 0.0075; // 设立static 成员变量的初值void main() { ... }为静态成员分配空间称为静态成员的定义。

但静态数据成员属于类,因此定义对象时并不为静态成员分配空间。

静态成员的定义一般出现在类的实现文件中。如在SavingAccount类的实现文件中,必须要如下的定义:

double SavingAccount::rate = 0.05;该定义为rate分配了空间,并给它赋了一个初值0.05。

如果没有这个定义,连接器会报告一个错误。

可以通过作用域操作符从类直接调用。如: SavingAccount::rate

但从每个对象的角度来看,它似乎又是对象的一部分,因此又可以从对象引用它。如有个SavingAccount类的对象obj,则可以用:obj.rate

由于是整个类共享的,因此不管用哪种调用方式,得到的值都是相同的。

2 静态变量的调用用类名加域作用符: print::a;

用对象名加取址符: class p1; p1.a;

3 静态成员函数与静态变量一样,在没有创建对象前即可通过类名调用。

1)静态成员函数只能访问 "静态成员变量",不能访问普通成员变量。

2)静态成员函数的使用规则和静态成员变量一样。

3)静态成员函数也有使用权限。类外无法访问私有静态函数。

4)普通成员函数可访问"静态成员变量",也可访问"非静态成员变量"

class BufferedOutput{public: short BytesWritten() { return bytecount;} static void ResetCount() { bytecout = 0;} static long bytecount;};long BufferedOutput::bytecount = 8;定义静态成员函数的主要目的是访问静态的数据成员。

如在SavingAccount类中,当利率发生变化时,必须修改这个静态数据成员的值。为此可以设置一个静态的成员函数:

static void SetRate(double newRate) {rate = newRate;}静态成员函数可定义为内嵌的,也可在类外定义。在类外定义时,不用static。

静态成员函数的访问:可以通过类作用域限定符或通过对象访问

类名::静态成员函数名();4 static关键字的作用1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值。

2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其他函数访问。

3)在模块内的static函数只可以被这一模块内的其他函数调用。这个函数的使用范围被限制在声明它的模块内。

4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝。

5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。

6) 对于静态(static)对象,当对象诞生时其构造式被执行;当程序将结束时(此对象因而将遭致毁灭)其析构式才被执行,但比全域对象的析构式早一步执行。

5 常见问题 1) 常量数据成员和静态常量数据成员有什么区别?如何初始化常量数据成员?如何初始化静态常量数据成员?

常量的数据成员指得是那些在对象生成时给定了初值,在整个对象的生命周期中,该数据成员的值是不能变的。常量数据成员的值必须在构造函数的初始化列表中进行初始化。静态的常量数据成员是整个类所有对象共享的一个常量。对整个类而言,不管定义了多少个对象,该成员永远只有一份拷贝。静态常量数据成员的值是在定义类时给定。

2) 静态成员函数不能操作非静态的数据成员,那么非静态的成员函数能否操作静态的数据成员?为什么?

因为静态成员函数没有隐含的this指针,所以不能够操作非静态的数据成员。静态的数据成员是所有对象共享的数据成员,在逻辑上是属于每一个对象的,所以非静态的成员函数可以操作静态的数据成员。

-End-

本文标签:函数静态成员

原文链接:https://www.xgfox.com/jsyd/521.html

本文版权:如无特别标注,本站文章均为原创。