static详情

1.C语言中的static

C语言中的static应用于普通变量和函数。
—变量
修饰全局变量时表明该变量只能在当前文件中使用;
未经初始化的静态全局变量会被程序自动初始化为0。

在全局变量前,加上关键字static,该变量就被定义成为一个静态全局变量。我们先举一个静态全局变量的例子,如下:

using namespace std;
void fn();  //声明函数
static int n;  //声明静态全局变量
int main()
{
    n = 20;  //为n赋初值
    cout<<n<<endl;//输出n的值
    fn();  //调用fn函数
}
void fn()
{
    n++;  //n的值自加一(n=n+1)
    cout<<n<<endl; //输出n的值
}

1)全局变量是不显式用 static 修饰的全局变量,全局变量默认是有外部链接性的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过 extern 全局变量名的声明,就可以使用全局变量。
2)全局静态变量是显式用 static 修饰的全局变量,作用域是声明此变量所在的文件,其他的文件即使用 extern 声明也不能使用。

修饰局部变量时延长该变量的生命周期–和成员声明周期一样,类似该变量具有记忆的功能,存放位置不同于函数体的局部变量。
在局部变量前,加上关键字static,该变量就被定义成为一个静态局部变量。如下:

#include <iostream>
using namespace std;
void fn();
int main()
{
    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()
{
    fn();
}
static void fn()//定义静态函数
{
    int n = 10;
    cout<<n<<endl;
}

2.C++中的static

C++中static叶修是变量,函数,但这里所指的时类中的成员变量和成员函数。
下面写一个求类中创建了多少对象的代码来展示

// 一个类创建了多少个对象  --计数
class Date
{
public:

	Date(int year, int month, int day)
		//对当前对象中的成员变量进行初始化
		: _year(year)
		, _month(month)
		, _day(day)
	{
		++_count;
		cout << "Date(int,int,int):" << this << endl;
	}
	Date() {

	}
	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._day)
	{
		++_count;
		cout << "Date(const Date&):" << this << endl;
	}
	Date& operator=(const Date& d)
	{
		cout << this << "=" << &d << endl;
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
	~Date()
	{
		_count--;
		cout << "~Date():" << this << endl;
	}
private:

	int _year;
	int _month;
	int _day;

public:
	static int _count;//静态成员变量
};
//int _count = 0; 采用全局变量可以实现,缺陷是可以任意修改
//静态成员变量在类外初始化
int Date::_count = 0;

void TestDate() {
	Date d(2021, 1, 1);
}
int main()
{

	cout << Date::_count << endl;
	Date d1,d2;
	cout << sizeof(d1) << endl;
	cout << sizeof(d2) << endl;

    
	cout << &d1._count << endl;
	cout << &d2._count << endl;
	return 0;
}

静态成员变量:没有包含在具体的对象中,是所有对象共享的成员变量,只有一份是类的属性。静态成员变量不会影响sizeof结果,上述类中定义的静态成员变量是public,否则就无法调用,当然,如果将权限改为private,又想调用,该怎么解决,这里就要用到静态成员函数,往下看。

class Date
{
public:

	Date(int year, int month, int day)
		//对当前对象中的成员变量进行初始化
		: _year(year)
		, _month(month)
		, _day(day)
	{
		++_count;
		cout << "Date(int,int,int):" << this << endl;
	}
	Date() {

	}
	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._day)
	{
		++_count;
		cout << "Date(const Date&):" << this << endl;
	}
	Date& operator=(const Date& d)
	{
		cout << this << "=" << &d << endl;
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
	~Date()
	{
		_count--;
		cout << "~Date():" << this << endl;
	}
	//静态成员函数
	static int GetCount() {
		return _count;
	}
private:

	int _year;
	int _month;
	int _day;

	static int _count;//静态成员变量
};
//int _count = 0; 采用全局变量可以实现,缺陷是可以任意修改
//静态成员变量在类外初始化
int Date::_count = 0;
int main()
{
	Date d;
	d.GetCount(); //对象.成员函数
	Date::GetCount(); //类名::成员函数
	return 0;
}

上面定义了一个静态成员函数,将静态成员函数作为静态成员的返回值,在主函数中调用静态成员函数,就可以。与上面的静态成员变量的结果一致。
特性:
静态数据成员
(1)静态数据成员可以实现多个对象之间的数据共享,它是类的所有对象的共享成员,它在内存中只占一份空间,如果改变它的值,则各对象中这个数据成员的值都被改变。
(2)静态数据成员是在程序开始运行时被分配空间,到程序结束之后才释放,只要类中指定了静态数据成员,即使不定义对象,也会为静态数据成员分配空间。
(3)静态数据成员可以被初始化,但是只能在类体外进行初始化,若未对静态数据成员赋初值,则编译器会自动为其初始化为 0。
(4)静态数据成员既可以通过对象名引用,也可以通过类名引用。

静态成员函数
(1)静态成员函数和静态数据成员一样,他们都属于类的静态成员,而不是对象成员。
(2)非静态成员函数有 this 指针,而静态成员函数没有 this 指针。
(3)静态成员函数主要用来方位静态数据成员而不能访问非静态成员。

使用方法:
对象.静态成员变量/函数类名::静态成员变量/函数

这里有几个小结论直接告诉大家 ,此处就不做演示了
1.不能通过类名来调用类的非静态成员函数,可以通过类的对象调用静态成员函数和非静态成员函数。
2.类的对象可以使用静态成员函数和非静态成员函数。
3.静态成员函数中不能引用非静态成员,在类的非静态成员函数中使用类的静态成员。

结尾彩蛋
细心的同学应该会发现上面有提到过extern,这里简单介绍一下。
在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。extern声明不是定义,即不分配存储空间。
在一个文件中定义了变量和函数, 在其他文件中要使用它们, 可以有两种方式:
1.使用头文件,然后声明它们,然后其他文件去包含头文件
2.在其他文件中直接extern

extern C
C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时无法找到对应函数的情况,此时C函数就需要用extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。
比如说你用C 开发了一个DLL 库,为了能够让C ++语言也能够调用你的DLL 输出(Export) 的函数,你需要用extern “C” 来强制编译器不要修改你的函数名。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值