#复习:
static成员独立于类对象而存在,也就是说它不属于某个对象的成员,它能被全体对象所共享。
上节课中统计类类型对象的个数,用static成员来实现。
非static成员它属于类对象,每个对象都有一份拷贝,无法达到共享的目的。
static成员函数没有this指针,它不能访问非static成员,也不能调用非static成员函数。
static成员函数使用类名::Functionname()完成访问,如:A::staticFun();
#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;
Date d2(2010); //只是想判定某一年是否是瑞年,不想创建对象,使用静态成员函数实现。
cout << d2.IsleapYear() << endl;
cout << Date::IsleapYear(2010) << endl; //这里使用静态成员函数,不用创建对象。
return 0;
}
本节内容:
1)四种对象的作用域与生存期
2)static用法总结
1)四种对象的作用域与生存期
栈对象:隐含调用构造函数(程序中没有显示调用)
堆对象:隐含调用构造函数(程序中没有显示调用)
全局对象、静态全局对象:
全局对象的构造先于main函数
已初始化的全局变量或静态全局对象存储于.data段中
未初始化的全局变量或静态全局存储于.bss段中
静态局部对象
已初始化的静态局部变量存储于.data段中
未初始化的静态局部变量存储于.bss段中
#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);
int main(void)
{
cout << "Eentering main..." << endl;
cout << n << endl;
Test t(10); //栈上创建的对象,在函数块中有效(生命周期),在生存期结束的时候自动释放。
{
Test t(20);
}
{
Test* t3 = new Test(30); //堆上创建的对象要显式释放(delete)
delete t3; //即使作用域结束,如果不显式调用delete,t3对象也不会释放。因此作用域与生存期不等同。
}
{
static int n3; //n3存储于.bss段中。(编译器初始化)
static int n4 = 100;//n4存储于.data段中。(编译器初始化)
static Test t4(333); //t4对象运行期初始化 .data段中
}
cout << "Exiting main..." << endl;
return 0;
}
/*
输出结果:
Test...100
Test...200
Eentering main...
0
Test...10
Test...20
~Test 20 ....
Test...30
~Test 30 ....
Test...333
Exiting main...
~Test 10 ....
~Test 333 ....
~Test 200 ....
~Test 100 ....
*/
2)static用法总结
1、(C中)用于函数内部修饰变量,即函数内的静态变量。这种变量的生存期长于该函数,使得函数具有一定的”状态“。使用静态变量的函数一般是不可重入的。也不是安全线程。比如strtok(3).
void foo()
{
static int n = 100; //函数调用完后,变量n还是存在的。例如第一次进入函数n =100,再次进入不会再分配空间了,还是100
n = 200; //当我们把n改为200,x下次调用仍是200.n变量是有状态的,这种函数是不可重入函数,不是线程安全的函数。
}
2、(C中)用在文件级别(函数体之外),修饰变量或函数,表示该变量或者函数只在本文件可见,其它文件看不到也访问不到该变量或函数。专业的说法叫”具有internal linkage“(简言之:不暴露给别的translation unit).
C语言中者两种用法很明确,一般也不容易混淆。
//假如
a.c中有static int n = 100;
b.c中有static int n = 100;//只在本文件可见,两文件中两者是可同时存在的,b.c看不到a.c中的n变量,a.c看不到b.c中的n变量
//如果a.c和b.c想共用同一个变量
a.c
int n = 100;
b.c
extern int n; //这种变量称为external linlage 外部联动
//全局变量必须在.c文件中定义,不要在.h文件中定义。
//如果在.h中定义全局变量,会报重复定义错误,如:x.h 中定义 int n = 100; a.c 中包含头文件.h,这样会有一个int n = 100,同理b.c中也有一个int n =100;重复定义。
由于C++中引入了类,在保持于C语言兼容的同时,static关键字又有了两种新用法:
3、用于修饰类的数据成员,即所谓”静态成员“。这种数据成员是每个instance有一份。
4、用于修饰class的成员函数,即所谓”静态成员函数“。这种成员函数只能访问静态成员和其它静态成员函数,不能访问非静态成员和非静态成员函数。因为没有this指针。