Static类成员
对于特定类类型的全体对象而言,访问一个全局对象有时是必要的。也许,在程序的任一点需要统计已创建的类对象的数量;或者,全局对象可能是指向类的错误处理例程的一个指针;或者,他是指向类类型对象的内存自由存储区的一个指针。
然而,全局对象会破坏封装:对象需要支持特定类抽象的实现。如果对象是全局的,一般的用户代码就可以修改这个值。类可以定义类静态成员,而不是定义一个可普遍访问的全局对象。
通常,非static数据成员存在于类类型的每个对象中。不像普通的数据成员,static数据成员独立于该类的任意对象而存在;每个static数据成员是与类关联的对象,并不是直接使用非static成员。
1.使用类的static成员的好处
(1)static成员的名字是在类的作用域中,因此可以避免与其他类的成员或全局对象名字冲突。
(2)封装,static成员可以使私有成员,而全局对象不可以。
(3)static成员是与特定类关联的。这种可见性可清洗地显示程序员的意图。
2.定义static成员
在成员声明之前加上关键字static将成员设为static。static成员遵循正常的公有/私有访问的规则。
一个简单的表示银行账户的类。每个账户具有余额和拥有者,并且按月获得利息,但应用于每个账户的力量总是相同的。可以按下面这样的编写这个类
1 class Account{ 2 3 public: 4 5 void applyint() { amout += amout * Rate; } 6 7 static double rate() { return Rate; } 8 9 static void rate(double); 10 11 private: 12 13 std::string owner; 14 15 double amout; 16 17 static double Rate; 18 19 static double initRate(); 20 21 };
这个类的每个对象都具有两个数据成员:owner和amout。对象没有与static数据成员对应的数据成员,但是,存在一个单独的Rate对象,有Account类型的每个对象共享。
3.使用类static成员
可以通过作用域操作符从类直接调用哪个static成员,或者是通过对象、引用或指向该类类型对象的指针间接调用。
1 Account ac1; 2 3 Account *ac2 = &ac1; 4 5 double rate; 6 7 rate = ac1.rate(); 8 9 rate = ac2->rate(); 10 11 rate = Account::rate();
如同使用其他成员一样,类成员函数可以不用作用域操作符来引用类的static成员:
1 class Account{ 2 3 public: 4 5 void applyint() { amout += amout * Rate; } 6 7 }
一、static成员函数
Account类有两个名为rate的static成员函数,其中一个定义在类的内部。当我们在类的外部定义static成员是,不必重复制定static关键字,该关键子只出现在类定义体内部的声明处:
1 void Account::rate(double newRate) 2 3 { 4 5 Rate = newRate; 6 7 }
static成员没有this指针:static成员是类的组成部分担不是任何对象的组成部分,因此,static成员函数没有this指针。通过使用非static成员显示或隐式地引用this是一个编译错误。
二、static数据成员
static数据成员可以声明为任意类型。static数据成员必须在类定义体的外部定义。
定义static数据成员的方式与定义其他类成员和变量的方式不同:向指定类型名,接着成员的完全限定名。
1 double Account:interestRate = initRate();
这个语句定义名为Rate的static对象,他是类Account的成员,为double型。像其他成员定义一样,一旦成员名出现,static成员的定义就是在类作用域内。因此,我们可以没有限定的使用名为InitRate的static成员函数,作为Rate的初始化。注意,尽管InitRate是私有的,我们仍然可以使用该函数初始化Rate。像其任意的其他成员定义一样,Rate定义实在累得作用于中,因此可以访问该类的私有成员。
1.特殊的整型const static成员
类的static成员,像普通的数据成员一样,不在类的定义体重初始化。相反,static数据成员通常在定义时才初始化。一个例外是,只要初始化是一个常量的表达式,整型 const static数据成员就可以在类的定义体中进行初始化:
1 Class Account { 2 3 public: 4 5 static double rate() { return Rate; } 6 staic void rate(double); 7 private: 8 9 static const int period = 30; 10 double _tbl[period]; 11 };
2.static数据成员不是类对象的组成部分
普通的成员都是给定类的每个对象的组成部分。static射程远独立 与任何对象而存在,不是类类型的组成部分。因为static数据成员不是任何对象的组成部分,所以他们的使用方式对于非static数据成员而言是不合法的。
例如,static数据成员的类型可以使该成员所属的类类型。非static成员被限定声明为其自身类对象的指针或引用:
1 class Bar { 2 3 public: 4 5 ////////// 6 private: 7 8 static Bar mem1; 9 10 Bar *mem2; 11 12 Bar mem3; 13 14 };
非static数据成员不能用作默认实参,因为他的值不能独立于所属的对象而使用。使用非static数据成员琢磨人实参,将无法提供对象以获取该成员的值,因此是错误都。