1 静态成员:在定义前面添加了static关键字的成员。
2 eg:
static int i; // 静态成员变量
static void init(){} // 静态成员函数
3 普通成员变量与静态成员变量的差别
(1)普通成员变量每个对象有各自的一份,而静态成员变量一共就有一份,为所有对象共享。
(2)sizeof运算符不会计算静态成员变量。
eg:
class CMyclass{
int n;
static int s;
}
则,sizeof(CMyclass)等于4,原因是静态成员变量不是放在对象内部,而是放在所有对象外面,被所有对象共享。
4 普通成员函数与静态成员函数差别
(1)普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象。
5 静态成员不需要通过对象就可以访问
6 如何访问静态成员
(1)类名::成员名 eg: CRectangle::PrintTotal();
(2)对象名.成员名 eg: CRectangle r; r.PrintTotal();
(3)指针->成员名 eg: CRectangle* p = &r; p->PrintTotal();
(4)引用.成员名 eg: CRectangle& ref = r; int n = ref.nTotalNumber;
7 静态成员变量本质上是全局变量,哪怕一个对象都不存在,类的静态成员变量也存在。
8 静态成员函数本质上是全局函数
9 设置静态成员这种机制的目的是将和某些紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于维护和理解。
10 静态成员例子(见本工程static.cpp)
/**
* 静态成员例子
* 考虑一个需要随时知道矩形总数和总面积的图形处理程序
* 可以用全局变量来记录总数和总面积
* 用静态成员将这两个变量封装进类中,就容易理解和维护
* */
#include <iostream>
#include "CRectangle.h"
using namespace std;
// 必须在定义类的文件中对静态成员变量进行一次说明或初始化。否则编译可以通过,链接不能通过。
int CRectangle::nTotalNumber = 0;
int CRectangle::nTotalArea = 0;
int main()
{
CRectangle r1(3, 3), r2(2, 2);
// cout << CRectangle::nTotalNumber; // wrong 私有
CRectangle::PrintTotal();
r1.PrintTotal(); // 虽然这么写,但是并不意味着PrintTotal作用在r1上面。
return 0;
}
11 在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。
原因:如下例子
void CRectangle::PrintTotal()
{
cout << w << "," << nTotalNumber << "," << nTotalArea << endl; // wrong
}
CRectangle::PrintTotal(); // 解释不通,w到底属于哪个对象
12 在10中CRectangle.cpp有何缺陷?
缺陷产生原因:在使用CRectangle类时,有时会调用复制构造函数生成临时的隐藏的CRectangle对象。
以下情况会产生缺陷:
调用一个以CRectangle类对象作为参数的函数时候
调用一个以CRectangle类对象作为返回值的函数时
这两种情况创建对象的时候不会使用自定义构造函数,而会使用编译器默认的复制构造函数,但是消亡的时候会调用析构函数,因此会产生错误。
是否所有构造函数都会使用自定义的构造函数进行初始化呢?不是
临时对象在消亡的时候会调用析构函数,减少nTotalNumber和nTotalArea的值,可是这些临时对象在生成时候却没有增加nTotalNumber和nTotalArea的值
解决办法:为CRectangle类写一个复制构造函数。
CRectangle::CRectangle(CRectangle& r)
{
w = r.w; h = r.h;
nTotalNumber ++;
nTotalArea += w*h;
}