有时候类需要它的一些成员和类本身直接相关,而不是与类的各个对象保持关联。
目录
声明静态成员
我们通过在成员声明之前加上关键字static使得其与类关联在一起。和其他成员一样,静态成员可以是public或private的。静态数据成员的类型可以是常量,引用,指针,类类型等。
举个例子:
//全局变量 利率
//double interestRate;
class Account {
public:
Account(std::string name, double money) :owner(name), amount(money) {}
double getAmount() const {
return this->amount;
}
void deposit(double money) {
this->amount += money;
}
double rate() { return interestRate; }
static void rate(double newRate){ //静态的成员函数不属于任何一个对象,所以this不能用,this指的是当前对象。
interestRate = newRate;
}
void applyint() { amount += amount * interestRate; }
private:
std::string owner;
double amount;
static double interestRate; //只有一个,不能在这初始化
static const int period = 30; //例外
};
double Account::interestRate = 0.015;
1.类的静态成员存在于对象之外,对象中不包含任何与静态成员有关的数据。
2.静态成员函数不和任何对象绑定在一起,所以它们不包含this指针。做我欸结果,静态成员不能声明成const的,而且我们也不能在static函数体内使用this指针。
使用类的静态成员
1.我们使用作用域运算符直接访问静态成员:
double r;
r=Account::rate();
2.虽然静态成员不属于类的某个对象,但是我们仍然可以使用类的对象,引用或者指针来访问静态成员:
Account ac1;
Account *ac2=ac1;
r=ac1.rate();
r=ac2->rate();
3.成员函数不通过作用域运算符就可以直接使用静态成员
定义静态成员
1.和其他成员函数一样,我们既可以在类的内部也可以在类的外部定义静态成员函数。当在类的外部定义静态成员时,不能重复static关键字,该关键字只出现在类内部的声明语句。
2.定义静态数据成员的方式和在类的外部定义成员函数差不多。我们需要指定对象的类型名,然后是类名,作用域运算符以及成员自己的名字:
//定义并初始化一个静态成员
double Account::interestRate=initRate();
解释一下:从类名开始,这条定义语句的剩余部分就位于类的作用域内了。因此,我们可以直接使用initRate函数。
Note:要想确保对象只定义一次,最好的方法是把静态数据成员的定义和其他非内联函数的定义放在同一个文件中。
静态成员的类内初始化
通常情况下,类的静态成员不应该在类的内部初始化。然而,我们可以为静态成员提供const整数类型的类内初始值,不过要求静态成员必须是字面值常量类型的constexpr。
例如,我们可以用一个初始化了的静态数据成员指定数组成员的维度:
class Account
{
public:
static double rate() {return interestRate;}
static void rate(double);
private:
static constexpr int period=30;
double daily_tbl[period];
}
Note:即使一个静态数据成员在类内部被初始化了,通常情况下也应该在类的外部定义一下该成员(以免有的程序找不到相关定义)
静态成员能用于某些场景,而普通成员不能
1.静态成员独立于任何对象。因此,在某些非静态成员可能非法的场合,静态成员却可以正常使用。举个栗子,静态成员可以是不完全类型。特别的,静态数据成员的类型可以就是它所属的类类型。而非静态数据成员则受到限制,只能声明成它所属类的指针或引用:
class Bar
{
public:
//...
private:
static Bar mem1;//正确
Bar *mem2;//正确
Bar mem3;//错误
}
2.静态成员和普通成员的另一个区别是我们可以使用静态成员作为默认实参:
class Screen
{
public:
Screen& clear(char=bkground);
private:
static const char bkground;
};