Static成员
概念
声明为static
的类成员称为类的静态成员,用static
修饰的成员变量,称之为静态成员变量;用static
修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。
例题:实现一个类,计算程序中创建了多少个类对象。
class A
{
public:
A() { ++_scount; }
A(const A& t) { ++_scount; }
~A() { --_scount; }
static int GetACount()
{
return _scount;
}
private:
static int _scount;//类中只是声明
};
int A::_scount = 0;//静态成员变量在类外定义
void TestA()
{
cout << A::GetACount() << endl;
A a1, a2;
A a3(a1);
cout << A::GetACount() << endl;
}
一共构造了3个类对象,其中a1
和a2
是调用构造函数、a3
是调用拷贝构造。
特性
- 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。
- 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。
- 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问。
- 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。
- 静态成员也是类的成员,受public、protected、private 访问限定符的限制。
问题
- 静态成员函数可以调用非静态成员函数吗?
答:不可以。由特性的第4点,静态成员函数没有this指针,所以不能调用非静态成员函数。
但是后面第3个问题是静态成员函数调用私有构造函数,因为构造函数不需要this指针。 - 非静态成员函数可以调用类的静态成员函数吗?
答:可以。因为类的静态成员函数属于整个类,是可以被非静态成员函数调用的。 - 设计一个只能在栈上定义对象的类
class StackOnly
{
public:
StackOnly(int x = 0, int y = 0)
:_x(x)
,_y(0)
{}
private:
int _x = 0;
int _y = 0;
}
int main()
{
StackOnly so1;//栈
static StackOnly so2;//静态区
}
我们正常写的StackOnly
类的对象可以在栈上定义,也可以在堆或者静态区上定义。这不符合我们的要求。
下面代码被注释的部分出现一个“先有鸡还是先有蛋的问题”。正常调用非静态StackOnly CreateObj()
函数需要有对象,比如so.CreateObj()
,可是对象创建不了,这样就矛盾了。于是想到使用静态成语函数。静态成员函数没有this指针不需要使用对象去调用,私有的成员函数在类里面可以被调用(在类外面不行)。
class StackOnly
{
public:
//虽然不适用静态函数创造的so一定在栈上,但是无法调用这个函数,因为首先要先构造对象
//StackOnly CreateObj()
//{
// StackOnly so;
// return so;
//}
static StackOnly CreateObj()
{
StackOnly so;
return so;
}
private:
//定义对象一定需要构造函数,所以先把“路”堵死
StackOnly(int x = 0, int y = 0)
:_x(x)
,_y(0)
{}
private:
int _x = 0;
int _y = 0;
}
int main()
{
//StackOnly so1;//栈
//static StackOnly so2;//静态区
StackOnly so3 = StackOnly::CreateObj();
}