目录
一、声明静态成员:
二、定义静态成员:
三、使用类的静态成员:
四、静态成员类内初始化:
五、静态成员与普通成员的区别:
六、案例代码:
类内的静态成员包括: 静态数据成员 和 静态成员函数。
类的静态成员存在于任何对象之外,对象中不包含任何与静态数据成员有关的数据。
一、声明静态成员:
在成员(函数 或 变量 )声明之前加上关键字 static。
静态成员可以是 public 或 private的。
静态数据成员的 类型 可以是 常量、引用、指针、类类型等。
class Account
{
public:Account(std::string name, double mount):owner(name),amount(mount){ }void calculate() {amount += amount * interestRate;std::cout << amount << std::endl;}//获取当前利率static double rate(){return interestRate;}//用于更新ratestatic void rate(double);private:std::string owner;double amount;static double interestRate;static double initRate();
};
上面例子中的静态成员有:
static double rate();static void rate(double);static double interestRate;static double initRate();
说明:
1. 每个Account对象将包含两个数据成员:owner 和 amount 。 只存在一个interestRate对象而且它被所有Account对象共享。
2. 静态成员函数,不与任何对象绑定在一起,它们不包含this指针,不能在static函数体内使用this指针。
3. 作为结果,静态成员函数不能声明成 const的。
二、定义静态成员:
1. 静态成员函数:
像其他成员函数一样,既可以在类的内部 ,也可以在类的外部定义静态成员函数。
当在类的外部定义静态成员函数时,不能重复static关键字,该关键字只出现在类内部的声明语句。
比如,上面定义的Account类中的rate函数,在类外的定义如下:
//在类外定义,静态成员函数,不包含 static关键字void Account::rate(double a)
{interestRate = a;
}
2. 静态数据成员:
静态数据成员,不是在创建类的对象时被定义的,它们不是由类的构造函数初始化的。(比如:上面定义的Account类中的静态数据成员 interestRate)
不能在类的内部初始化静态成员,必须在类的外部定义 和 初始化每个静态成员 。 一个静态数据成员只能定义一次。
类似于全局变量,静态数据成员定义在任何函数之外。 因此一旦被定义,就将一直存在于程序的整个生命周期中。
//定义并初始化一个静态成员
double Account::interestRate = initRate();
【定义了名为 interestRate 的对象,该对象是 类Account的静态成员, 其类型是double。 从类名开始,这条语的剩余部分就都位于类的作用域之内了,因此可以直接调用initRate函数。】
三、使用类的静态成员:
使用作用域运算符直接访问静态成员:
double current_rate;
// 通过 域运算符,调用rate()函数,获取当前的利率
current_rate= Account::rate();Account ac1;
Account* ac2 = &ac1;//通过对象(指针),调用rate()函数,获取当前的利率
current_rate = ac1.rate();
current_rate = ac2->rate();
静态成员 不属于类的某个对象,但 仍可以使用 类的对象、引用 或 指针 来访问静态成员。
四、静态成员类内初始化:
虽然类的 静态成员 不应该在类的内部初始化, 但是,C++中可以为 字面值常量类型 constexpr 的静态成员 提供 const 整数类型(只是 整数类型)的类内初始值。初始值 必须是 常量表达式。
class Account
{
public:....
private:static constexpr int period = 100;double daily_table[period];
}
五、静态成员与普通成员的区别:
静态成员独立于对象, 而 普通成员是和具体的对象关联的。
区别一:
静态成员可以是不完全类型。 特别的,静态数据成员的类型可以是它所属的类类型; 而非静态数据成员则受到限制,只能声明成 它所属累的指针或引用:
class Bar
{
public:.....
private:static Bar mem1;Bar* mem2; //正确:指针成员可以是不完全类型Bar mem3; //错误:数据成员必须是完全类型
}
区别二:
可以使用静态成员作为 默认实参。
class Screen
{
public://bkground表示一个在类中稍后定义的静态成员Screen& clear(char = bkground);private:static const char bkground;
}
六、案例代码:
有的时候类需要它的一些成员与类本身直接相关 , 而不是与类的各个对象关联。 例如,一个银行的账户类中有一个数据成员来表示当前的基准利率,每个类的对象都能够使用该基准利率,并且一旦利率浮动,所有的对象都能使用新值。
staitc_content.h 头文件如下:
#ifndef _STATIC_CONTENT_H
#define _STATIC_CONTENT_H
#include<string>class Account
{
public:Account(std::string name, double mount):owner(name),amount(mount){ }void calculate() {amount += amount * interestRate;std::cout << amount << std::endl;}static double rate(){return interestRate;}//用于更新ratestatic void rate(double);private:std::string owner;double amount;static double interestRate;static double initRate();
};
//定义并初始化一个静态成员
//静态成员,并不属于某一个类的对象,而是属于类
//因为从类名 Account后面开始,剩余的部分都位于类的作用域之内,因此可以直接使用initRate函数
double Account::interestRate = initRate();void Account::rate(double a)
{interestRate = a;
}double Account::initRate()
{return 0.0;
}#endif
static_content.cpp 代码如下:
#include <iostream>
#include"static_content.h"int main()
{Account my("my",100);std::cout << my.rate() << std::endl;//变更利率my.rate(6.7);std::cout << "my的利率 " << my.rate() << std::endl;Account Xiaohui("Xiao Hui",200);std::cout << "Xiao hui的利率 "<<Xiaohui.rate() << std::endl;
}
代码执行的结果如下: