按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
静态成员(变量与函数)
我想你已经很清楚了,如果你依据一个类别产生出三个对象,每一个对象将各有一份成
员变量。有时候这并不是你要的。假设你有一个类别,专门用来处理存款帐户,它至少
应该要有存户的姓名、地址、存款额、利率等成员变量:
class SavingAccount
{
private:
char m_name'40'; // 存戶姓名
char m_addr'60'; // 存戶址
double m_total; // 存款額
double m_rate; // 利率
。。。
};
这家行库采用浮动利率,每个帐户的利息都是根据当天的挂牌利率来计算。这时候
m_rate 就不适合成为每个帐户对象中的一笔资料,否则每天一开市,光把所有帐户内容
85
…………………………………………………………Page 148……………………………………………………………
叫出来,修改m_rate 的值,就花掉不少时间。m_rate 应该独立在各对象之外,成为类
别独一无二的资料。怎么做?在m_rate 前面加上static 修饰词即可:
class SavingAccount
{
private:
char m_name'40'; // 存户姓名
char m_addr'60'; // 存户地址
double m_total; // 存款额
static double m_rate; // 利率
。。。
};
static 成员变量不属于对象的一部份,而是类别的一部份,所以程序可以在还没有诞生任
何对象的时候就处理此种成员变量。但首先你必须初始化它。
不要把static 成员变量的初始化动作安排在类别的构造式中,因为构造式可能一再被调
用,而变量的初值却只应该设定一次。也不要把初始化动作安排在头文件中,因为它可
能会被包含许多地方,因此也就可能被执行许多次。你应该在实作档中且类别以外的任
何位置设定其初值。例如在main 之中,或全域函数中,或任何函数之外:
double SavingAccount::m_rate = 0。0075; // 设立static 成员变量的初值
void main() { 。。。 }
这么做可曾考虑到m_rate 是个private 资料?没关系,设定static 成员变量初值时,
不受任何存取权限的束缚。请注意,static 成员变量的型别也出现在初值设定句中,因为
这是一个初值设定动作,不是一个数量指定(assignment )动作。事实上,static 成员变
量是在这时候(而不是在类别声明中)才定义出来的。如果你没有做这个初始化动作,
会产生联结错误:
error LNK2001: unresolved external symbol 〃private: static double
SavingAccount::m_rate〃(?m_rate@SavingAccount@@2HA)
关于static 成员的使用实例,第6章的HelloMFC 有一个,附录D的「自制DBWIN 工
具(MFC 版)」也有一个。第3章的「RTTI (执行时期型别辨识)」一节仿真MFC 的
CRuntimeClass,也有一个static 应用实例。
86
…………………………………………………………Page 149……………………………………………………………
第2章 C++ 的重要性伲�
下面是存取static 成员变量的一种方式,注意,此刻还没有诞生任何对象实体:
// 第一种存取方式
void main()
{
SavingAccount::m_rate = 0。0075; // 欲此行成立,须把 m_rate 改为public
}
下面这种情况则是产生一个对象后,透过对象来处理static 成员变量:
// 第二种存取方式
void main()
{
SavingAccount myAccount;
myAccount。m_rate = 0。0075; // 欲此行成立,须把 m_rate 改为public
}
你得搞清楚一个观念,static 成员变量并不是因为对象的实现而才得以实现,它本来就存
在,你可以想象它是一个全域变量。因此,第一种处理方式在意义上比较不会给人错误
的印象。
只要access level 允许,任何函数(包括全域函数或成员函数,static 或non…static )都可
以存取static 成员变量。但如果你希望在产生任何object 之前就存取其class 的private
static 成员变量,则必须设计一个static 成员函数(例如以下的setRate ):
class SavingAccount
{
private:
char m_name'40'; // 存户姓名
char m_addr'60'; // 存户地址
double m_total; // 存款额
static double m_rate; // 利率
。。。
public:
static void setRate(double newRate) { m_rate = newRate; }
。。。
};
double SavingAccount::m_rate = 0。0075; // 设置 static 成员变量的初值
void main()
87
…………………………………………………………Page 150……………………………………………………………
第篇 勿在浮砂築高台
{
SavingAccount::setRate(0。0074); // 直接调用类別的 static 成员函数
SavingAccount myAccount;
myAccount。setRate(0。0074); // 通过对象调用 stati c 成员函数
}
由于static 成员函数不需要借助任何对象,就可以被调用执行,所以编译器不会为它暗
加一个this 指针。也因为如此,static 成员函数无法处理类别之中的non…static 成员变
量。还记得吗,我在前面说过,成员函数之所以能够以单一一份函数码处理各个对象的
资料而不紊乱,完全靠的是this 指针的指示。
static 成员函数「没有this 参数」的这种性质,正是我们的MFC 应用程序在准备
callback 函数时所需要的。第6章的Hello World 例中我就会举这样一个实例。
C++ 程序的生与死:兼谈构造式与析构式
C++ 的new 运算子和C 的malloc 函数都是为了配置内存,但前者比之后者的优点
是,new 不但配置对象所需的内存空间时,同时会引发构造式的执行。
所谓构造式(constructor ),就是对象诞生后第一个执行(并且是自动执行)的函数,它
的函数名称必定要与类别名称相同。
相对于构造式,自然就有个析构式(destructor ),也就是在对象行将毁灭但未毁灭之前
一刻,最�