(P17)对象的使用:static成员,static成员函数小结,四种对象的作用域与生存期

tech2022-08-11  118

文章目录

1.static成员,static成员函数小结2.四种对象作用域与生存期3.static用法总结

1.static成员,static成员函数小结

static成员独立于类对象而存在,也就是说它不属于某个对象的成员,它不能被全体对象所共享统计类类型对象创建的个数,用static成员来实现非static成员它属于类对象,每个对象都有一份拷贝static成员函数访问方式:通过类名,eg:A::statusFunc()来访问的,所以没有传递this指针,因而不能访问非static成员(因为非static属于某个对象,需要通过this指针来引用),也不能调用非static成员函数对象的作用域与生存期不等同 (1)作用域指的是该变量可见的范围 (2) 在堆上创建的对象,没有调用delete的话,该对象就不会被释放,也就是他的生存期还是存在的 (3)栈上对象的作用域与生存期是等同的eg:static成员函数的用法 17cpp\17cpp\17cpp\01.cpp #include <iostream> using namespace std; class Date { public: Date(int year) : year_(year) { } //判断年份是否是闰年 static bool IsLeapYear(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 ==0); } bool IsLeapYear() { return (year_ % 4 == 0 && year_ % 100 != 0) || (year_ % 400 ==0); } private: int year_; }; int main(void) { Date d(2012); cout<<d.IsLeapYear()<<endl; //使用静态成员函数,不需要创建一个日期对象,就能访问,就能直接判断该日期是否是闰年 cout<<Date::IsLeapYear(2010)<<endl; return 0; } 测试:

2.四种对象作用域与生存期

栈对象 隐含调用构造函数(程序中没有显示调用),是自动释放的

堆对象 隐含调用构造函数(程序中没有显示调用),但是没有显示释放

全局对象、静态全局对象 全局对象的构造先于main函数 已初始化的全局变量或静态全局对象存储于.data段中 未初始化的全局变量或静态全局对象存储于.bss段中

静态局部对象 已初始化的静态局部变量存储于.data段中 未初始化的静态局部变量存储于.bss段中

内存布局如下: (1).bss段和.data端区别: .bss段特点:在可执行文件中不占用空间,因为变量的初始值为0,只需要符号即可,在程序加载的时候才分配了这样的一个段 .data段在可执行文件中是占用空间的 (2)一些常量存放在代码段中

eg:17cpp\17cpp\17cpp\02.cpp #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段中。(bss含义:block started by symbol) int n2 = 100; // 已初始化的全局变量,初始值为100。n2存储于.data段中。 Test g(100); // 全局对象的构造先于main函数 static Test g2(200); //静态全局对象的构造也先于main函数 int main(void) { cout<<"Entering main ..."<<endl; cout<<n<<endl; //作用域在main的括号之内(块作用域) Test t(10); // 栈上创建的对象,在生存期结束的时候自动释放 { Test t(20); } { Test* t3 = new Test(30); // 堆上创建的对象,要显示释放 delete t3; } { //注意局部静态类对象和局部静态变量的区别 static int n3; // n3存储于.bss段中 (在编译期初始化,在编译的时候就会分配空间) static int n4 = 100; // n4存储于.data段中 (在编译期初始化,在编译的时候就会分配空间) //t4对象的作用域范围是在块作用域范围内,但是生存期是在整个程序范围之内 static Test t4(333); // t4对象在运行期初始化,存储于.data段 } cout<<"Exiting main ..."<<endl; } 测试: static Test t4(333);是在第一次运行的时候初始化的

3.static用法总结

(1)用于函数内部修饰变量,即函数内的静态变量。这种变量的生存期长于该函数,使得函数具有一定的“状态”。使用静态变量的函数一般是不可重入的,也不是线程安全的,比如strtok(3)。

(2) 用在文件级别(函数体之外),修饰变量或函数,表示该变量或函数只在本文件可见,其他文件看不到也访问不到该变量或函数。专业的说法叫“具有internal linkage”(简言之:不暴露给别的translation unit编译单元)。 C语言的这两种用法很明确,一般也不容易混淆。

由于C++引入了类,在保持与C语言兼容的同时,static关键字又有了两种新用法:

(3)用于修饰类的数据成员,即所谓“静态成员”。 这种数据成员的生存期大于class的对象(实例/instance)。 静态数据成员是每个class有一份,普通数据成员是每个instance 有一份。

(4) 用于修饰class的成员函数,即所谓“静态成员函数”。 这种成员函数只能访问静态成员和其他静态成员函数,不能访问非静态成员和非静态成员函数

对上述static用法总结中(1)的具体说明

当程序执行出了该函数之后,该变量还是存在的; 第一次进来的时候初始化,第二次进来的时候不会为该变量分配空间了; 如果n的值该为200,那么下一次用到该函数的时候,变量n不再分配空间,第二次进来的时候n的值已经成了200 这种函数是有状态的,称之为不可重入的函数,也是线程不安全的,不会用在信号处理函数中

void foo() { static int n = 100; n = 200; } 对上述static用法总结中(2)的具体说明

下面这样定义是可以的 a.c看不到b.c中的n变量

a.c文件中 static int n = 100; b.c文件中 static int n = 100; internal linkage,对其他编译单元不可见 这两个变量是2个独立的空间 ================================ 如果要共享同一个变量 a.c文件中 int n = 100; external linkage,对其他编译单元可见 b.c文件中 b.c访问的变量和a.c访问的变量是同一个变量,也就是所谓的全局变量(全局变量要在.c文件中定义) extern int n; 也可以将extern int n放文件b.c中的头文件中,相当于外部声明了 ============================== 错误用法,会造成重定义的问题: x.h 在x.h文件中定义全局变量 int n = 100; a.c 包含x.h头文件后,相当于定义了int n = 100; b.c 包含x.h头文件后,,相当于定义了int n = 100; 这样会造成重定义的问题
最新回复(0)