在类的定义中,成员主要分为两类:静态成员以及非静态成员,关于非静态成员的内存布局,可参见
http://blog.csdn.net/xuqingict/article/details/26157585
所谓“静态”,从关键字static可以知道,类的static成员是属于整个类所有的。是类的所有对象共享的变量。
在下述类中,重点讨论类的静态成员变量。
例1:
类的static对象可以是任意的类型,例如int,很简单,如下:
#include <iostream>
class A{
private:
static int a;
};
int A::a = 1;
int main(void)
{
return 0;
}
其中的成员变量a是一个静态的成员变量。初始化是通过类的作用域符号来进行的。
其次,值得一提的是,如果a是private的话,那么该成员变量在类外是不可以使用A::a来进行访问的。这其实可以定义一个静态成员
函数来操作该变量即可。由于这不是本文的重点,故忽略之。可参见:http://blog.csdn.net/morewindows/article/details/6721430
例2:该类的对象作为类的成员变量,如下:
#include <iostream>
#include <cstdio>
using namespace std;
class Point3d
{
public:
Point3d(){
cout << "constructor called" << endl;
}
virtual ~Point3d(){
cout << "destructor called" << endl;
cout << "a: " << Point3d::a << endl;}
public:
float x,y,z;
private:
static int a;
static Point3d origin;
};
Point3d Point3d::origin;
int Point3d::a = 10;
int main()
{
cout << "main func entered..." << endl;
return 0;
}
可以看到,在main函数执行之前,调用了一次类的构造函数,在main函数执行完毕之后,调用了一次析构函数,但是期间我并没有定义对象。或许你已经想到,这就是静态的成员变量origin的创建。
也就是说静态成员变量在main函数开始之前就将静态的数据成员以及变量创建在了全局的数据段上。并且该静态成员在函数执行完毕之后,由于此时已经超出了类的作用域的范围,那么该静态对象被析构,调用了析构函数。
因此,编译器会在main函数之前插入一些内部的代码来就绪静态成员变量,也会在超出类的作用域之后,撤销该静态对象。
也就是说,即使该类没有定义任何的对象,在该类定义完成之后,类的静态成员变量就已经就绪了。
updated:类中的成员变量的访问方式主要分为以下三种:
1 通过对象来访问(这是最常用的方式,虽然静态成员变量独立于类的所有的对象,但是所有的对象时共享静态成员变量的)
2 通过类作用域符号来访问。
3 这里的方式非常的奇葩!!这是我第一次见到,很惊奇。
假设类名为Point, 类似 ((Point *)0)->staticMember;
上述访问方式对于成员函数也是适用的,参见下面的一段简单的代码:
#include
#include
using namespace std;
class Point
{
private:
int x;
int y;
public:
static const int Member;// 定义静态成员变量Member
static int getMember() {return Member;} //静态成员函数,其中该函数可以访问静态成员变量,全局变量,以及该函数自己的参数三种类型的数据
Point(int _x,int _y):x(_x),y(_y){}
};
const int Point::Member = -23; //对成员变量进行初始化。
int main()
{
Point p(1,2);
Point *pt = &p;
cout << p.Member << "\t" << pt->Member << endl; //使用对象来访问静态数据成员
cout << Point::Member << endl; //使用类作用域符号来访问该变量
cout << &Point::Member << endl; //取静态数据的地址,返回的是该数据在内存中的地址,与non-static数据不同(返回的是在对象布局中的偏移量)
cout << ((Point *)0)->Member << endl; //这是我说的奇葩的方式,通过将0转化为一个this指针实例,类访问静态成员变量的值
//对于静态成员函数同样拥有上面的结论!!!
cout << ((Point *)0)->getMember() << endl;
printf("add: %p\n",&(Point::getMember));
return 0;
}
执行结果为: