static成员是与类相关的,而不是与类的各个对象保持关联。
实际上,这在一定程度上减少了资源开销。
想象类内某const int size,每个对象的值都应当是相同的,如果单纯的将其定义为const成员,那么每一个对象都会有一个size的副本,浪费资源。
由于类内static是整个类的所有对象共享,所以它没有this指针!
由于是类内static,所以static也会有不同的访问权限。
public static
static data and static function
这种用法并不常见,看下面的例子:
`#include <iostream>
using namespace std;
class Test
{
public:
static int x;
static void fun(){
cout << "Calling public static function fun()" << endl;
}
};
int Test::x = 10;//类内声明,类外定义
int main()
{
Test test;
cout << Test::x << endl;
cout << test.x << endl;
test.fun();
Test::fun();
return 0;
}
其中x和fun()是static成员,访问权限是public。这意味着该类的对象从类外即可轻松访问x和fun()。
注意这里强调,static function 是没有this指针的,所以test.fun()
实际上只是通过test调用了Test类的fun(),和test并无关系。
test.x同理。
可见这种调用方式可能会产生歧义,因此更建议使用ClassName::static data
的调用方式。
private static
private static是最为常用的方式。
因为访问权限是static,所以有很好的封装性。对于类内经常用到的操作,可以将其抽象成一个工具函数(tool function)方便使用
,因为这个tool function是属于整个类的,因此将其编写为static更能节省空间。
#include <iostream>
using namespace std;
class Test
{
private:
static int maxSize;
static void toolFunction();//do something in the class
public:
static void accessMaxSize();
};
int main()
{
Test test;
return 0;
}
maxSize是private data,那么以前的test.maxSize
和Test::masSize
这两种用法都不能访问maxSize
对于这种数据想要完成访问操作,需要定义一个public static method,正如类中的static void accessMaxSize()
。
static const 成员
这里是比较容易弄混的地方,看下面这个例子。
#include <iostream>
using namespace std;
class Test
{
private:
static const int maxSize = 5;
int array[maxSize];
public:
Test(){
cout << &maxSize << endl;
}
};
int main()
{
Test test;
return 0;
}
Test类中声明了一个static const int maxSize
,并且赋予初值,作为成员array[]的长度参数
,直到这里一切都OK,但是
你会发现,上述代码无法通过编译。
编译器提示
**undefined reference to
Test::maxSize’|**`
使用未定义的成员?
等等?我们不是给予了初值了吗?
实际上,如果去掉上述代码的构造函数部分的cout << &maxSize << endl;
语句编译器就会开心的放你通过。
这很奇怪,为什么对maxSize
取地址编译器就报错呢?
这意味着编译器没有给maxSize
分配空间,也就是说,maxSize
未定义!
Effective C++ 是这样解释的:
我们看到的
static const int maxSize = 5
是一个声明式而非定义式。c++要求对任何一个东西提供定义式,但是如果是class专属常量且为static且为integral(ints,chars,bools),则需特殊处理,只要不取它的地址,编译器一切都ok。
最好的解决办法是,在类外提供一个定义式
const int Test::maxSize;
需要注意的是,不要const int Test::maxSize = someValue
,即便这个someValue
是5也不可以,编译器会提示
error: duplicate initialization of 'Test::maxSize'|
触发重定义错误。