C++ static 在类中的扩展【C++】(zc)

static 修饰类

C++扩展了 static 在类中的语意,用于实现在同一个类,多个对象间数据共享,协调行为的目的。
静态变量有全局变量的优势,又不会像全变量一样被滥用。
而这一类变量,即可以通过类来管理,也可以通过类的静态函数来管理。
类的静态成员,属于类,也属于对象,但终归属于类。

static 修饰数据成员

语法规则

在这里插入图片描述

#include <iostream>
using namespace std;

class MyClass
{
public:
	MyClass()
	{
		_m = 100;
		_n = 200;
	}
	~MyClass()
	{}

	int _m;
	int _n;
	static int _share = 100;

};


int main()
{
	MyClass a;
	cout << a._share << endl;
	return 0;
}

上面代码在编译的时候会报错:
在这里插入图片描述

所以:static修饰数据成员需要初始化,不可以类内初始化。

在类外初始化,并且需要类名空间,且不需要static

#include <iostream>
using namespace std;

class MyClass
{
public:
	MyClass()
	{
		_m = 100;
		_n = 200;
	}
	~MyClass()
	{}

	int _m;
	int _n;
	static int _share;

};

int MyClass::_share = 100;

int main()
{
	MyClass a;
	cout << a._share << endl;
	return 0;
}

运行结果为:
在这里插入图片描述

类的声明与实现分开的时候如果把初始化放在了class.h里面之后就会出现class.h即include在了class.cpp又include 在了main.cpp 就会出现重复声明,出现错误。所以static修饰变量初始化在class.cpp文件里面。并且我们把声明放在.h文件里面,把定义放在.cpp文件里面。

B.h

#pragma once
class B
{
public:
	B();
	
	static int _m;  //声明
};

B.cpp

#include "B.h"

int B::_m = 200;  //定义

B::B()
{

}

main.c

#include "B.h"
#include <iostream>
using namespace std;

class MyClass
{
public:
	MyClass()
	{
		_m = 100;
		_n = 200;
	}
	~MyClass()
	{}

	int _m;
	int _n;
	static int _share;

};

int MyClass::_share = 100;

int main()
{
	MyClass a;
	cout << a._share << endl;
	return 0;
}

Static声明的数据成员不占用类对象的大小,存储在data段的rw段
在同一个类中,定义的类内成员m和n存储在内存中的栈区,
两个分区的变量通过MyClass类产生关系来维系其为整体。

#include <iostream>
using namespace std;

class MyClass
{
public:
	MyClass()
	{
		_m = 100;
		_n = 200;
	}
	~MyClass()
	{}

	int _m;
	int _n;
	static int _share;

};

int MyClass::_share = 100;

int main()
{
	MyClass a;
	cout << a._share << endl;
	cout << sizeof(MyClass) << endl;
	cout << sizeof(a) << endl;
	return 0;
}

运行结果为:
在这里插入图片描述

大小都是8,占用的是两个类内私有数据成员int类型的大小。

访问

类的静态成员,属于类,也属于对象,但终归属于类。
既可以通过对象访问,也可以不通过对象,直接通过类名访问。

#include <iostream>
using namespace std;

class MyClass
{
public:
	MyClass()
	{
		_m = 100;
		_n = 200;
	}
	~MyClass()
	{}

	int _m;
	int _n;
	static int _share;

};

int MyClass::_share = 100;




int main()
{
	MyClass a;
	cout << a._share << endl;
	cout<<MyClass::_share << endl;
	return 0;
}

在这里插入图片描述m和n的存在依赖于对象的生成,static修饰的数据成员在对象还没有生成的时候就已经存在了。并且属于命名空间MyClass,所以就有了上面的第二种访问方式。即使没有对象生成也可以进行访问,前提是不受private的限制。如果有private的限制也不可以进行访问。

static 修饰数据成员小结

在这里插入图片描述

static 修饰成员函数

为了管理静态成员,C++提供了静态函数,以对外提供接口。并且静态函数只能访问静态成员。
我们前面说过,如果static修饰的类内数据成员被private限制之后就不能直接使用命名空间进行访问。而需要使用函数,但是static修饰的类内数据成员是在类对象生成之前就已经存在的,所以不能使用类内私有成员函数对于static修饰的数据成员进行操作。所以我们需要在没有对象的时候也可以管理static修饰的数据成员,那么我们就需要使用static修饰函数,目的就是为了管理静态变量。
统计函数的执行次数:

#include <iostream>
using namespace std;

class MyClass
{
public:
	MyClass()
	{
		_m = 100;
		_n = 200;
	}
	~MyClass()
	{}

	void foo()
	{
		cout << "void foo()" << endl;
		fooCount++;
	}

	static int invokefoofCount()
	{
		return fooCount;
	}

private:
	int _m;
	int _n;
	static int fooCount;

};

int MyClass::fooCount = 0;



int main()
{
	{
		MyClass a, b, c;
		a.foo();
		b.foo();
		c.foo();
		cout << a.invokefoofCount() << endl;
	}
	cout << MyClass::invokefoofCount() << endl;
	return 0;
}

运行结果为:

在这里插入图片描述

一塔湖图

实现多个学校各自有一塔,一湖,但是共用一个图书馆

#include <iostream>
using namespace std;

class Univesity
{
public:
	Univesity(string t, string l)
	{
		_tower = t;
		_lake = l;
	}

	static string & getLib()
	{
		return _lib;
	}

	void dis()
	{
		cout << "塔:" << _tower << "湖:" << _lake << "图:" << _lib << endl;
	}

private:
	string _tower;
	string _lake;
	static string _lib;
};

string Univesity::_lib = " ";


int main()
{
	Univesity pk("博雅塔","未名湖");
	Univesity bs("电视台","大明湖");
	Univesity xdf("雷峰台", "东方湖");
	Univesity::getLib() += "计算机基础 ";
	pk.dis();
	Univesity::getLib() += "数据结构 ";
	bs.dis();
	Univesity::getLib() += "计算机网络 ";
	xdf.dis();
	return 0;
}

运行结果为:
在这里插入图片描述

私有成员可以通过返回引用的方式修改数据。

体现出来图书馆共享

语法规则

static修饰成员函数的作用主要用来管理静态变量
类内声明,类外定义方式:

#include <iostream>
using namespace std;

class MyClass
{
public:
	MyClass()
	{}
	~MyClass()
	{}
	static void manageA();


private:
	static int a;
};

int MyClass::a = 100;

void MyClass:: manageA()
{

}

int main()
{
	
	return 0;
}

静态成员函数只能访问静态成员变量和静态成员函数,不能访问非静态的成员变量和成员函数。

#include <iostream>
using namespace std;

class MyClass
{
public:
	MyClass()
	{}
	~MyClass()
	{}
	static void manageA();
	static void manageB()
	{}
	void foo()
	{

	}
private:
	static int a;
	int x;
};

int MyClass::a = 100;

void MyClass:: manageA()
{
	cout << a <<endl;
	manageB();      //编译通过
	cout << x <<endl; //编译器报错:非静态成员必须与特定对象相对
	foo(); //编译器报错:非静态成员必须与特定对象相对
}

int main()
{
	
	return 0;
}

对于上面MyClass类:

int main()
{
	MyClass a;
	a.manageA();
	a.manageB();

	MyClass::manageA();
	MyClass::manageA();

	return 0;
}
a.manageA();
a.manageB();

里面会有默认的参数this指针,所以可以访问到类内的所有成员变量和成员函数。
但是:

MyClass::manageA();
MyClass::manageA();

上面这种情况没有对象,那么就没有this指针,所以只能访问static 修饰的类内数据成员和类内函数。
静态成员函数中没有this指针。

非静态函数访问静态的成员:

#include <iostream>
using namespace std;

class MyClass
{
public:
	MyClass()
	{}
	~MyClass()
	{}
	static void manageA();
	static void manageB()
	{}
	void foo()
	{
cout << a << endl;
		manageA();
	}
private:
	static int a;
	int x;
};

int MyClass::a = 100;

void MyClass:: manageA()
{
	cout << a <<endl;
}

int main()
{
	MyClass a;
	return 0;
}

非静态成员可以访问static修饰的变量和成员。

应用:协调:取号服务

#include <iostream> 
using namespace std;
class Server
{
public:
	Server(char name)
		:_name(name) {}
	void serverOne()
	{
		if (_openFlag && _lastServedIdx < _turnCount)
		{
			_lastServedIdx++;
			cout << "Server: " << _name << " is serving " << _lastServedIdx << endl;
		}
		if (_lastServedIdx >= _turnCount)
			_openFlag = false;
	}
	static int getTurn()

	{
		++_turnCount;
		return _turnCount;
	}
	static bool stillOpen()
	{
		return _openFlag;
	}
private:
	char _name;
	static int _turnCount;
	static int _lastServedIdx;
	static bool _openFlag;
};
int Server::_turnCount = 0;
int Server::_lastServedIdx = 0;
bool Server::_openFlag = true;
int main()
{
	Server s1('A'), s2('B');
	int num;
	cout << "How many in your groups" << endl;
	cin >> num;
	cout << "your turns are" << endl;
	for (int i = 0; i < num; i++)
	{
		cout << Server::getTurn() << endl;
	}
	do
	{
		s1.serverOne();
		s2.serverOne();
	} while (Server::stillOpen());
	cout << "now closing server" << endl;
	return 0;
}

运行结果为:

在这里插入图片描述

修饰成员函数小结

在这里插入图片描述

发布了163 篇原创文章 · 获赞 94 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43648751/article/details/104599865