c++ primer 学习笔记:类之static 类成员

来源:互联网 发布:英魂之刃英雄数据库 编辑:程序博客网 时间:2024/05/22 04:40

对于特定类类型的全体对象而言,访问一个全局对象有时是必要的。也许,在程序的任意点需要统计已创建的特定类类型对象的数量;或者,全局对象可能是指向类的错误处理

例程的一个指针;或者,它是指向类类型对象的内在自由存储区的一个指针。然而,全局对象会破坏封装:对象需要支持特定类抽象的实现。如果对象是全局的,一般的用户代码就可以修改这个值。类可以定义类静态成员,而不是定义一个可普遍访问的全局对象。

通常,非static 数据成员存在于类类型的每个对象中。不像普通的数据成员,static 数据成员独立于该类的任意对象而存在;每个 static 数据成员是与类关联的对象,并不与该类的对象相关联。

正如类可以定义共享的static 数据成员一样,类也可以定义 static 成员函数。static 成员函数没有 this 形参,它可以直接访问所属类的 static 成员,但不能直接使用非static 成员。

使用类的static 成员的优点

1.static 成员的名字是在类的作用域中,因此可以避免与其他类的成员或全局对象名字冲突。
2.可以实施封装。static 成员可以是私有成员,而全局对象不可以。
3.通过阅读程序容易看出static 成员是与特定类关联的。这种可见性可清晰地显示程序员的意图。 

定义static 成员

在成员声明前加上关键字static 将成员设为 static。static 成员遵循正常的公有/私有访问规则。
class Account {public:// interface functions herevoid applyint() { amount += amount * interestRate; }static double rate() { return interestRate; }static void rate(double); // sets a new rateprivate:std::string owner;double amount;static double interestRate;static double initRate();};

static 函数没有 this 指针

static 成员是类的组成部分但不是任何对象的组成部分,因此,static 成员函数没有 this 指针。通过使用非 static 成员显式或隐式地引用 this 是一个编译时错误。因为static 成员不是任何对象的组成部分,所以 static 成员函数不能被声明为 const。毕竟,将成员函数声明为const 就是承诺不会修改该函数所属的对象。最后,static 成员函数也不能被声明为虚函数。

static 数据成员

static 数据成员必须在类定义体的外部定义(正好一次)。不像普通数据成员,static 成员不是通过类构造函数进行初始化,而是应该在定义时进行初始化。
定义static 数据成员的方式与定义其他类成员和变量的方式相同:先指定类型名,接着是成员的完全限定名。
可以定义如下interestRate:
// define and initialize static class memberdouble Account::interestRate = initRate();
这个语句定义名为interestRate 的 static 对象,它是类 Account 的成员,为 double 型。像其他成员定义一样,一旦成员名出现,static 成员的就是在类作用域中。因此,我们可以没有限定地直接使用名为initRate 的 static 成员函数,作为 interestRate 初始化式。注意,尽管 initRate 是私有的,我们仍然可以使用该函数来初始化interestRate。像任意的其他成员定义一样,interestRate 的定义是在类的作用域中,因此可以访问该类的私有成员。
像使用任意的类成员一样,在类定义体外部引用类的static 成员时,必须指定成员是在哪个类中定义的。然而,static 关键字只能用于类定义体内部的声明中,定义不能标示为static。

特殊的整型const static 成员

一般而言,类的static 成员,像普通数据成员一样,不能在类的定义体中初始化。相反,static 数据成员通常在定义时才初始化。这个规则的一个例外是,只要初始化式是一个常量表达式,整型const static 数据成员就可以在类的定义体中进行初始化:
class Account {public:static double rate() { return interestRate; }static void rate(double); // sets a new rateprivate:static const int period = 30; // interest posted every 30 daysdouble daily_tbl[period]; // ok: period is constant expression};
用常量值初始化的整型const static 数据成员是一个常量表达式。同样地,它可以用在任何需要常量表达式的地方,例如指定数组成员 daily_tbl 的维。
const static 数据成员在类的定义体中初始化时,该数据成员仍必须在类的定义体之外进行定义。
在类内部提供初始化式时,成员的定义不必再指定初始值:
// definition of static member with no initializer;// the initial value is specified inside the class definitionconst int Account::period;

static 成员不是类对象的组成部分

普通成员都是给定类的每个对象的组成部分。static 成员独立于任何对象而存在,不是类类型对象的组成部分。因为 static 数据成员不是任何对象的组成部分,所以它们的使用方式对于非static 数据成员而言是不合法的。
例如,static 数据成员的类型可以是该成员所属的类类型。非 static 成员被限定声明为其自身类对象的指针或引用:
class Bar {public:// ...private:static Bar mem1; // okBar *mem2; // okBar mem3; // error};

类似地,static 数据成员可用作默认实参:
class Screen {public:// bkground refers to the static member// declared later in the class definitionScreen& clear(char = bkground);private:static const char bkground = '#';};
非static 数据成员不能用作默认实参,因为它的值不能独立于所属的对象而使用。使用非 static 数据成员作默认实参,将无法提供对象以获取该成员的值,因而是错误的。



原创粉丝点击