Essential C++学习记录&笔记整理25(静态类成员)

有些难度了。尽量搞清楚!

静态类成员

引子

  • 这是个什么东西呢?就是比如你在定义类的时候,私有成员有定义一个容器。但是,你为了程序运行效率,你在定义这个类的类对象的时候,你不想复制那个私有成员的容器,为嘛?要是容器长度太大了,复制起来占不占时间?
  • 所以呢,你就把那个private:里定义的容器设置成静态类型的,举个例子:
class Triangular{
public:
	//...
private:
static vector<int>_elems;

你看这个格式,我把私有成员的vector容器定义成静态类型的,也就是静态类成员,既然我不想复制容器,那我所有定义的类对象(Triangular类的类对象)是不是就共用这一个容器? 对吧,所以我们可以得知:静态数据成员用来表示唯一的,可共享的成员。它可以在同一类的所有对象中被访问。

  • 那这样有什么好处呢?比如说你定义了一个静态数据成员(静态类成员)是个容器,这个容器因为是共用的,比如我想在某个类对象里查找容器里的一个元素,我直接找就完了,我还用复制容器或者我自己再手动往里头添元素?找不到,我就往里面填进去查找的元素呗(一般是知道这是个什么数列,查找的元素用户不会乱写,乱写有乱写的处理方法)。
  • 好,那我再通过同一个类的类对象去查找容器里之前要查找的元素,这个元素在之前在容器里没有被找到,然后我不就添加进去了吗,这时候我再找,不就找到了?方便吗?我还用再复制一遍这个容器或者手动填元素再找吗?当然这只是一个例子,其实静态类成员还有其他用处和讲究。待我慢慢剖析讲解。
  • 其实说到了这里,我认为静态类成员就像是放在qq群上的公共资源库,大家(类对象)随便提取或上传资源到这个库里,增删查改都行(局限性的增删查改,管理员可以随便操作哈哈哈)。所以我想定义成静态类成员一定要融会贯通这个举例,遵守规则(下面讲)
  • 对于类而言,静态数据成员只有唯一的一份实体,所以我们必须在类的头文件附属的程序代码文件提供清楚的定义。静态数据成员的名称必须附上类作用域运算符,如:
vector<int>Triangular::_elems;
//在比如Triangular.cpp里写这两行代码
int Triangular::_initial_size=8;
//_initial_size是静态数据成员(静态类成员),
//我可以在类头文件的程序代码文件里给它初始化。
  • 如果我想在类成员函数里访问静态数据成员,可以按照访问非静态数据成员一样访问静态数据成员:
if(_elems.size()<elem_cnt)
{
	gen_elements(elem_cnt);
}

这里就访问了_elems这个静态数据成员(容器),访问了它的长度通过泛型算法.size()。

  • 对于const型静态数据成员,必须在声明这个成员的时候给它赋定初值
class intBuffer{
public:
	//...
private:
	static const int _buf_Size=1024;//赋定初值
	int _buffer[_buf_size];

静态成员函数

  • 一般情形下,成员函数必须通过其类的类对象调用,同时这个类对象会被绑定到该成员函数的this指针(this指针指向其调用成员函数的类对象(房子里指向房子整体)通过存储于每个类对象中的this指针,成员函数才能够访问存储于每个类对象中的非静态数据成员,嗯这点很重要,通过this指针,我们就可以访问类私有成员啦!
  • 某些类成员函数并未访问类的非静态数据成员,执行这种函数不会影响类对象的什么。所以可以很方便的用非成员函数的方式(调用一般自定义函数的方式)来调用这种类成员函数,但是我必须在这种类成员函数前加类作用域运算符:
bool Triangular::
is_elem(int value)
{
	if(!_elems.size()||_elems[_slems.size()-1]<value)
	{
		gen_elems_to_value(value);
		//如果静态数据成员(容器里)
		//是空的或者值大于了容器最后一个元素的值
		//就把这个传进来的value扔进容器里(一般是push_back(value))
		//到容器最后,数列嘛。
	}
	vector<int>::iterator found_it;
	vector<int>::iterator end_it=_elems.end();
	//泛型指针的定义,分别指向容器的被查找到的元素
	//和容器的末尾元素的位置的下一个位置
	//我可不可以定义在一起呢?少写一个vector<int>::iterator
	//答案是,我的天呐,完全可以!我在cb编译器上写了
	//也是容器类型的泛型指针(vector<string>型)的
	//vector<string>::iteratorit=find(slist.begin(),slist.end(),sval),it22;
	//虽然我没对it22作什么操作,但是编译器仍然通过
	//并正常运行程序。
	//泛型指针也可
	//所以你就写成
	//vector<int>::iterator found_it,end_it=_elems.end();
	//found_it直接声明的时候赋初值都行。
	
	//通过泛型算法给泛型指针赋值一个容器里被查找到的元素的地址
	//(有可能没找到,此时赋值给这个泛型指针容器的末尾元素的位置的下一个位置地址。
	return found_it!=end_it;
	//巧妙的bool表达式,因为这个类成员函数返回类型是bool类型
	//所以通过这样的关系运算符判断,可得知return true还是false
}
if(Triangular::is_elem(8))
{
	//...
}//这样的方式调用并未访问任何非静态数据成员(非静态类成员)的成员函数

这样的方式调用,就能让编译器或者程序阅读者知道我们想调用哪个类的成员函数is_elem().

  • 所以我们说静态成员函数可以在和对象没有任何关系的情形下(如不改对象里的其他数据成员的值)被调用。
  • 注意,成员函数必须在不访问任何非静态成员的条件下才能被声明为static,否则把这种成员函数声明成static将毫无意义。声明静态成员函数的方式如下:
class Triangular{
public:
	static bool is_elem(int);
	static void gen_elemnts(int length);//声明函数时变量名可写可不写
	static void gen_elems_to_value(int value);
	static void display(int length,int beg_pos,ostream &os=cout);
	//提供默认参数值,输出到屏幕上,你可以不提供第三个实参。
	//...
private:
	static const int _max_elems=1024;
	static vector<int>_elems;
};//注意这个;别忘了。
  • 当我们在类主体外进行成员函数的定义的时候,如果声明该成员函数
    时最前头加了static,则定义时最前头不用再写static了,举个例子:
//最前头没有写static
void Triangular::gen_elems_to_value(int value)
{
	//...
}

PS:书上这一节的例子我敲入计算机里,输出结果和书上的有出入,所以我未给出实战例子。望路过的小伙伴们指正,感谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值