目录
static成员
- 对于特定类型的全体对象而言,有时候可能需要访问一个全局的变量。比如说统计某种类型对象已创建的数量。
- 如果我们用全局变量会破坏数据的封装,一般的用户代码都可以修改这个全局变量,这时我们可以用类的静态成员来解决这个问题。
- 非static数据成员存在于类类型的每个对象中,static数据成员独立该类的任意对象存在,它是与类关联的对象,不与类对象关联。
static成员优点
扫描二维码关注公众号,回复:
2510382 查看本文章
- static成员的名字是在类的作用域中,因此可以避免与其它类成员或全局对象名字冲突。
- 可以实施封装,static成员可以是私有的,而全局对象不可以
- 阅读程序容易看出static成员与某个类相关联,这种可见性可以清晰地反映程序员的意图。
static成员的定义
- static成员需要在类定义体外进行初始化与定义
- 特殊的整型static const成员
- 整型static const成员可以在类定义体中初始化,该成员可以不在类体外进行定义
static成员函数
- static成员函数没有this指针
- 非静态成员函数可以访问静态成员
- 静态成员函数不可以访问非静态成员,也不能访问非静态成员函数
类/对象大小计算
- 类大小计算遵循前面学过的结构体对齐原则
- 类的大小与数据成员有关与成员函数无关
- 类的大小与静态数据成员无关
- 虚函数对类的大小的影响
- 虚继承对类的大小的影响
四种对象作用域与生存期
- 栈对象
- 堆对象 new malloc
- 全局对象、静态全局对象:全局对象的构造先于main函数,已初始化的全局变量或静态全局对象存储于.data段中,未初始化的全局变量或静态全局对象存储于.bss段中
- 静态局部对象:已初始化的静态局部变量存储于.data段中,未初始化的静态局部变量存储于.bss段中
代码段会存储常量。C++中不区分。.bss和.data
#include <iostream>
using namespace std;
class Test
{
public:
Test(int n) : n_(n)
{
cout<<"Test "<<n_<<" ..."<<endl;
}
~Test()
{
cout<<"~Test "<<n_<<" ..."<<endl;
}
private:
int n_;
};
int n; // 未初始化的全局变量,初始值为0。n存储于.bss段中。(block started by symbol)
int n2 = 100; // 已初始化的全局变量,初始值为100。n2存储于.data段中。
Test g(100); // 全局对象的构造先于main函数
static Test g2(200);
int main(void)
{
cout<<"Entering main ..."<<endl;
Test t(10); // 栈上创建的对象,在生存期结束的时候自动释放
{
Test t(20);
}
{
Test* t3 = new Test(30); // 堆上创建的对象,要显示释放
delete t3;
}
{
static int n3; // n3存储于.bss段中 (编译期初始化)
static int n4 = 100; // n4存储于.data段中 (编译期初始化)
static Test t4(333); // t4对象运行期初始化 .data段
}
cout<<"Exiting main ..."<<endl;
}
static用法总结
1. 用于函数内部修饰变量,即函数内的静态变量。这种变量的生存期长于该函数,使得函数具有一定的“状态”。使用静态变量的函数一般是不可重入的,也不是线程安全的,比如strtok(3)。
2. 用在文件级别(函数体之外),修饰变量或函数,表示该变量或函数只在本文件可见,其他文件看不到也访问不到该变量或函数。专业的说法叫“具有internal linkage”(简言之:不暴露给别的translation unit)。
C语言的这两种用法很明确,一般也不容易混淆
由于C++引入了类,在保持与C语言兼容的同时,static关键字又有了两种新用法:
3.用于修饰类的数据成员,即所谓“静态成员”。这种数据成员的生存期大于class的对象(实例/instance)。静态数据成员是每个class有一份,普通数据成员是每个instance 有一份。
4. 用于修饰class的成员函数,即所谓“静态成员函数”。这种成员函数只能访问静态成员和其他静态程员函数,不能访问非静态成员和非静态成员函数
const成员函数
- const成员函数不会修改对象的状态
- const成员函数只能访问数据成员的值,而不能修改它
const对象
- 如果把一个对象指定为const,就是告诉编译器不要修改它
- const对象的定义:const 类名 对象名(参数表);
- const对象不能调用非const成员函数
mutable
用mutable修饰的数据成员即使在const对象或在const成员函数中都可以被修改