一、前言
C++的关键字static分两种用法,在面向过程程序设计(c语言中的普通变量和函数)中的使用和在面向对象程序设计(c++中的类)中的使用
二、面向过程程序设计中的static(静态变量、静态函数)
内存分布 | 特性 |
---|---|
代码区 | 存放代码 |
全局数据区 | 全局静态变量和局部静态变量 |
堆 | 一般程序的由new产生的动态数据 |
栈 | 函数内部的自动变量。随着函数退出而释放 |
静态全局变量
静态全局变量特点
- 该变量在全局数据区分配内存
- 未经初始化的静态全局变量会被程序自动初始化为0(自动变量的值是随机的,除非它被显式初始化)
- 静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的,即不可以被其他文件引用
- 其它文件中可以定义相同名字的变量,不会发生冲突(若为全局非静态变量则会发生冲突)
#include<iostream>
using namespace std;
static int n; //定义静态全局变量
void func()
{
n++;
cout<<n<<endl;
}
int main(void)
{
n = 20;
cout<<n<<endl;
func();
return 0;
}
静态局部变量
静态局部变量的特点
- 该变量在全局数据区分配内存
- 静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化
- 静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0
- 它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束
#include<iostream>
using namespace std;
void fn();
int main(void)
{
fn();
fn();
fn();
return 0;
}
void fn()
{
static int n = 10;
cout<<n<<endl;
n++;
}
静态函数
静态函数特点
- 静态函数不能被其它文件所用
- 其它文件中可以定义相同名字的函数,不会发生冲突
#include<iostream>
using namespace std;
static void fn(); //声明静态函数
int main(void)
{
fn();
return 0;
}
void fn() //定义静态函数
{
int n = 10;
cout<<n<<endl;
}
二、面向对象程序设计中的static(静态数据成员(类)、静态成员函数)
静态成员数据
静态成员数据特点
- 作为类的成员,无论有多少对象,都只有一份拷贝,节省空间。该类所有对象都可以访问,在没有产生类的实例时就可以使用。
- 储存在全局数据区,在定义时才分配空间,不能在类声明中定义(在类外定义),定义(初始化)的格式:<数据类型><类名>::<静态数据成员名>=<值>
- 访问类的静态数据成员 两种格式:<类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名>(后一种需要静态数据成员为public成员)
- 用于各个对象都有相同属性,例如存款类,每个实例的利息相同,则可以将利息设为静态数据成员。
与全局变量相比,静态数据成员:
- 不会与全局命名空间中的其他相同名字冲突
- 实现信息隐藏。可以为private。
#include<iostream>
using namespace std;
class Myclass
{
private:
int a , b , c;
static int sum; //声明静态数据成员
public:
Myclass(int a , int b , int c);
void GetSum();
};
int Myclass::sum = 0; //定义并初始化静态数据成员
Myclass::Myclass(int a , int b , int c)
{
this->a = a;
this->b = b;
this->c = c;
sum += a+b+c;
}
void Myclass::GetSum()
{
cout<<"sum="<<sum<<endl;
}
int main(void)
{
Myclass M(1 , 2 , 3);
M.GetSum();
Myclass N(4 , 5 , 6);
N.GetSum();
M.GetSum();
return 0;
}
静态成员函数
静态成员函数特点
- 静态成员函数可以访问静态数据成员和静态成员函数,即静态成员之间可以互相访问
- 静态成员函数不可以访问非静态成员函数和非静态数据成员
- 非静态成员函数既可访问非静态数据成员又可以访问静态数据成员和静态成员函数
- 调用类的静态成员函数: <类名>::<静态成员函数名>(<参数表>)
- 调用对象的静态成员函数: <类对象名>.<静态成员函数名>(<参数表>)
- 是类的内部实现,属于类定义的一部分。不属于某个类对象,而属于类所有对象。
- 普通成员函数隐含了this指针(缺省),它指向类对象本身,如函数func()实际为this->func()。
- 静态成员函数不含this指针,因为不与任何对象相关。无法访问类对象的非静态数据成员和非静态成员函数,只能调用静态成员函数。
- 与全局函数相比,静态成员函数访问速度更快,因为没有this指针的额外开销
#include<iostream>
using namespace std;
class Myclass
{
private:
int a , b , c;
static int sum; //声明静态数据成员
public:
Myclass(int a , int b , int c);
static void GetSum(); //声明静态成员函数
};
int Myclass::sum = 0; //定义并初始化静态数据成员
Myclass::Myclass(int a , int b , int c)
{
this->a = a;
this->b = b;
this->c = c;
sum += a+b+c; //非静态成员函数可以访问静态数据成员
}
void Myclass::GetSum() //静态成员函数的实现
{
//cout<<a<<endl; //错误代码,a是非静态数据成员
cout<<"sum="<<sum<<endl;
}
int main(void)
{
Myclass M(1 , 2 , 3);
M.GetSum();
Myclass N(4 , 5 , 6);
N.GetSum();
Myclass::GetSum();
return 0;
}