Chinaunix首页 | 论坛 | 博客
  • 博客访问: 204867
  • 博文数量: 70
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 412
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-30 11:07
文章分类

全部博文(70)

文章存档

2014年(68)

2013年(2)

我的朋友

分类: C/C++

2014-03-12 17:45:14

举例:
#include
using namespace std;
class Student                   //定义Student类
{public:
Student(int n,int a,float s):num(n),age(a),score(s){ }      //定义构造函数
void total( );
static float average( );      //声明静态成员函数
private:
int num;
int age;
float score;
static float sum;            //静态数据成员
static int count;            //静态数据成员
};
这就是静态函数和静态变量的声明。

静态成员变量
当将类的某个数据成员声明为static时,该静态数据成员只能被定义一次,而且要被同类的所有对象共享。各个对象都拥有类中每一个普通数据成员的副本,但静态数据成员只有一个实例存在,与定义了多少类对象无关。静态方法就是与该类相关的,是类的一种行为,而不是与该类的实例对象相关。静态数据成员的用途之一是统计有多少个对象实际存在。
静态数据成员不能在类中初始化(对于常量静态类变量有待考证,好像可以在类外或main()函数之前定义,初始化可以放在类中),在其中指定初值是不允许的。静态成员也不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值。也不能在类的构造函数中初始化该成员,因为静态数据成员为类的各个对象共享,否则每次创建一个类的对象则静态数据成员都要被重新初始化。因此,静态数据成员一般在类外和main()函数之前初始化,注意:不能用参数初始化表对静态成员初始化,缺省时初始化为0。静态数据成员用来定义类的各个对象所公有的数据,比全局变量更安全。
一般形式:
数据类型类名::静态数据成员名=初值


静态成员函数
静态成员函数属于整个类,不属于某个对象,由该类所有对象共享。静态成员可定义为inline函数。一般情况下静态成员函数用于访问同一类中的静态数据成员或全局变量,而不访问非静态成员,如需访问非静态成员,需要将对象作为参数,通过对象名访问该对象的非静态成员。而非静态成员函数可以任意地访问静态成员函数和静态数据成员。
静态成员函数也可以在类外定义,此时不可以用static修饰。
例子
#include "iostream"
using namespace std;
class test
{
private:
     int x;
     int y;
public:
     static int num;
     static int Getnum()//在类内定义
     {
          x+=5;   // 这行代码是错误的,静态成员函数不能调用非静态数据成员,要通过类的对象来调用。
          num+=15;
          return num;
     }
};
int test::num = 10;
int main(void)
{
     test a;
     cout<      test::num = 20;
     cout<      cout<      cout<      system("pause");
     return 0;
}
在类外定义:
 int test::Getnum()
     {
       .........
     }
注意:
1、static函数同 数据成员一样,其所有者是类本身和对象,但是多有对象拥有一样的静态成员。从而在定义对象是不能通过构造函数对其进行初始化。
2、静态成员不能在类定义里边初始化,只能在class body外初始化。
3、静态成员仍然遵循public,private,protected访问准则。
4、静态成员函数没有this指针,因为它属于被所有对象共享,它不能返回非静态成员,因为除了对象会调用它外,类本身也可以调用。
5、由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
6、C++静态成员和静态成员函数的使用:静态成员的调用格式:类名::静态数据成员名、对象名.静态数据成员名、对象指针->静态数据成员、对象引用.静态数据成员(但类中很少会出现公有数据成员,这段仅仅讨论语法,未考虑实际运用中的数据封装问题)。静态成员函数的调用格式:类名::静态成员函数名、对象名.静态成员函数名、对象指针->静态成员函数名、对象引用.静态数据成员。静态成员函数没有this指针,因它不与特定对象相联系,调用时推荐使用“类名::静态成员函数名”格式。总结来说,在有对象的情况下,可以用调用普通类成员函数、普通成员变量的方式调用静态成员函数和静态成员变量。从这里可以看出静态成员变量和静态成员函数的使用应该是在不建立任何对象的情况下调用它们。其应用可以参见设计模式中Singleton pattern。
7、静态成员函数存在的原因是什么呢?主要是在建立任何对象之前可用它来访问静态数据成员,普通函数不能实现此功能。

网络上有很多关于解决静态成员函数访问普通成员变量的方法,总结如下:

方法一:声明类的所有数据成员都是静态的。运用这种方式的话,静态的成员函数就能够直接地访问它们,例如:

此时,即可在staticfunc()中正常访问变量a了,如果还需访问add()函数,则将add()也冠以static即可.

该方法缺点是,很多情况下,你并不愿意将所有的变量都改成静态成员.或者有些变量不能是静态的.此时该方法失效.

 

 

 

方法二:传入对象参照信息:

静态成员函数staticfunc()会使用参照Obj来访问非静态成员a.

 

将一个参照或者指针作为静态成员函数的自变量传递,就是在模仿自动传递非静态成员函数里this自变量这一行为。

 

 

该方法很明确,给静态函数传入this指针.

一般来说静态成员函数的参数没有严格的要求时,采用这种方法不失为妙招.如果静态成员函数的传入参数有严格的限制,就是说不能传入实体引用时,就不能使用这种方法了.

方法三:申明空指针

这种方法在类只有一个实体时可行,因为传入的this指针是一个全局量,始终指向最后定义的那个实体,当定义了第n+1个实体候,第n个实体的this指针就被忘掉了.在这种方法的启发下,我采用了下面的方法,比较麻烦些,但确实可行.之所以可行,前提是静态成员函数是一个回调函数,它返回了一个实体标识,但有别于this指针.

方法四:定义全部量(可以是数组,也可是链表)保存每个this指针

定义结构体:


然后在每次生成实体时:

其中Insert()功能为将this指针和实体标识video_handle加入链表.相当于将每个实体标识与其对应的this指针保存起来了.所以在回调函数中使用时只需根据回调函数返回的实体表示video_handle来查找对应的this即可.

问题终于解决,麻烦的就是要增加对链表的操作.



阅读(1972) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~