3-7:类与对象下篇——static成员

Posted 快乐江湖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3-7:类与对象下篇——static成员相关的知识,希望对你有一定的参考价值。

(1)一个问题经典的面试题

有一个经典的面试题:需要你实现一个类,以此计算出在这个工程中这个类一共实例化出了多少对象

我们知道,实例化对象时一定会调用构造函数或拷贝构造,所以你的想法可能是这样:定义一个计数器,然后在构造和拷贝构造中分别进行计数,如下

class A
{
public:
	A()//构造函数
	{
		++_cout;
	}
	A(const A& t)//拷贝构造
	{
		++_cout:
	}
	

private:
	int _cout;
}

但是你却忘记了一点,这里的计数器cout是类里面的变量,所以每新实例化一个类,它总会置为0,因此不可能达到目的的。

因此C++中引入了static成员来解决

(2)static成员

修改上述代码如下,将cout修改为静态成员

class A
{
public:
	A()//构造函数
	:_cout(0)
	{
		++cout;
	}
	A(const A& t)//拷贝构造
	{
		++cout:
	}
	

private:
	static int _cout;
}
  • 我们知道静态变量是存放在静态区的,也就是它本质和成员函数一样并不在这个类里面,所以即便它是int类型的,但是这个类的大小也依然是1
    在这里插入图片描述

好的现在还有一个问题——如何初始化?难道是放在初始化列表?但是这样做每次实例化类的时候就被更新了。
那么我们将其尝试放在类的外面初始化,如下
在这里插入图片描述
但是编译器报出了上面的错误,看来是编译器分不清到底用户要输出哪一个_cout了

所以我们初始化时要加上类的作用域限制符,并将其放在类的外面
在这里插入图片描述
好的现在目的已经达到了,我们已经可以通过_cout来统计这个类一共实例化了多少个类,但是怎么把它输出来呢。直接访问?显然不可能,这是一个私有成员。

所以我们可以实现一个函数通过返回值获取

在这里插入图片描述

  • 这里需要说明一点,很多人看见a1.getcout,总感觉这是对象a1的getcout函数,这其实是不正确的,因为getcout是存在于静态区的,这样做的作用只是为了突破类域,去访问到他

上面这个函数属于非静态成员函数,非静态成员函数在调用时需要使用实例化后的对象来突破类域,也就是不能直接用类名去调用这个函数,从另外一个方面解释,是因为非静态成员函数有this指针
在这里插入图片描述
而如果在这个函数前面加上static,那么非静态成员函数将变为静态成员函数,静态成员函数最大的特点就是没有this指针,所以这里就可以使用类名去调用函数,或者说突破类域了
在这里插入图片描述

  • 需要注意静态成员函数不能访问非静态成员变量:静态成员函数没有this指针,所以就不能访问非静态的成员变量,因为非静态的东西不是静态的,是变化的,必须随时要有this指针指向它。

(3)总结

1:静态成员是所有类共享的,不属于某个具体的对象

  • 这一点可以由上面案例中的计数器说明

2:静态成员变量需要在类的外面定义,定义时突破类域,不需要添加static

  • 比如int A::_cout=0;

3:静态成员函数没有this指针,不可以访问非静态成员

以上是关于3-7:类与对象下篇——static成员的主要内容,如果未能解决你的问题,请参考以下文章

类与对象(下篇)

类与对象(下篇)

C++从入门到入土第五篇:类与对象(下篇)

C++初阶:类和对象(下篇)初始化列表 | static成员 | 友元

[ C++ ] 类与对象(下) 初始化列表,友元,static成员,内部类

3-6:类与对象下篇——构造函数中的初始化列表匿名对象和explicit关键字