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++初阶:类和对象(下篇)初始化列表 | static成员 | 友元