类的静态成员分为两种类型, 一个是静态成员变量, 另一个是静态成员函数。
在这里总结一下,并给出一些例子,以防日后自己忘记。
一、静态成员变量
1. 静态成员变量的声明定义
静态成员变量就是在类的成员变量的前面加上static关键字,静态数据成员也遵守public/protected/private访问规则。类的静态成员变量不属于某个对象,而是属于整个类域的全局变量。它的声明定义如下:
test.h
class test
{
public:
static const int i; //声明,标准c++支持有序类型在类体中初始化
};
test.cpp
const int test::i = 0;
一定要注意不要在类的头文件定义静态成员变量,因为这样会引起重复定义的错误,即使加上#ifndef #define #endif或者#pragma once也是没有用的。
2. 静态成员变量被类所有对象和集成类所共有
派生类和基类对象共享基类的静态成员。
举个例子:
/*base.h*/
class base
{
public:
static int i;//声明
};
/*base.cpp*/
base::i = 0;
/*derived.h*/
class derived : public base
{};
/*main.cpp*/
void mian()
{
base a;
derived b;
a.i++;
cout << a.i << endl;
b.i++;
cout << b.i << endl;
}
输出1, 2可见类的基类和派生类的对象共享静态成员变量。
3.静态数据成员作为成员函数的可选参数
类的静态成员变量可以成为类的成员函数的可选参数但是普通变量则不可以。
class base{
public :
static int _staticVar;
int _var;
void foo1(int i=_staticVar);//正确,_staticVar为静态数据成员
void foo2(int i=_var);//错误,_var为普通数据成员
};
4. 静态成员可在类中声明为所属类的类型
静态成员可在类中声明为所属类的类型,但是,普通的成员变量则不可以 ,可以声明为所属类的引用和指针。例如:
class base{
public :
static base object1;//正确,静态数据成员
base object2;//错误 普通成员变量不能声明为所属类本身
base *pObject;//正确,指针
base &mObject;//正确,引用
};
二、静态成员函数
静态成员函数中是不能调用非静态成员的,包括非静态成员函数和非静态成员变量。那么在非静态成员函数中是否可以调用静态成员函数呢?答案是肯定的,因为静 态成员函数属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员函数的。其实,我们也可以以一个内存模型这个角度来考 虑,也就是说,无论采取什么样的操作,程序代码都是在内存中运行的,只有在内存中占有了一席之地,我们才能访问它。如果一个成员函数或成员变量还没有在内 存中产生,结果是无法访问它的。所有静态成员函数只能访问静态成员变量。
静态成员函数的声明与定义
/*test.h*/
class test
{
public:
static void foo();//声明
}
/*test.cpp*/
void test::foo()//定义
{}
三、一些相关例子
1.通过类名调用静态成员函数和非静态成员函数
/*test.h*/
class test
{
void init()
{ }
static void output()
{}
};
/*main.cpp*/
void main()
{
test::init();//错误,因为init是类的普通成员变量不能这样访问
test::output();//正确
}
结论:不能通过类名来调用类的非静态成员函数
2.通过类的对象调用静态成员函数和非静态成员函数
还是上面的类
/*main.cpp*/
void main ()
{
test a;
a.init();//正确
a.output();//正确
}
结论:类的对象可以使用静态成员函数和非静态成员函数。
3.使用类的静态成员变量
/*test.h*/
class test
{
test()
{
num++;
}
~test()
{
num--;
}
static void output()
{
cout << num <<endl;
}
private :
static int num;
};
/*main.cpp*/
void main()
{
test a;
a.output();
}
这段代码可以通过编译阶段 但是在链接的时候会出现问题,这是因为类的静态变量在使用前必须先初始化。在main()函数前面加上int test::num = 0;
结论:类的静态成员变量必须先初始化再使用。