类和static的纠缠无非就是两种。成员函数被static修饰,称为静态成员函数;另一种是成员数据被static修饰,称为静态成员数据。
通过需求出发,引入概念。理解用在什么地方,至于怎么用可以通过翻看代码来回忆。
静态成员变量
静态成员变量是用来干嘛?
需求:创建对象的时候我们想去统计创建了多少份,此时如果我们通过普通的数据成员是没去办法统计的。因为创建完对象以后这些数据都被该对象复制了一份,每个都是独立的。所以我们需要一个很特殊的数据他不属于某一个对象,但是每个对象却可以访问修改它。这个数据就是static静态成员变量。
1、使用静态数据实现
Man.h
#ifndef _MAN_H_
#define _MAN_H_
class Man {
public:
Man(); // 默认构造函数
~Man(); // 析构函数
int getCount();
private:
static int manCount; // 静态成员用来统计创建的对象
// static int manCount = 0; static静态变量不能在这里初始化
// static const int manCount = 0; const修饰的静态成员可以在这里初始化,但是C++11标准才支持
};
#endif
Man.cpp
#include "../include/Man.h"
int Man::manCount = 0; // 静态成员数据在实现中初始化,而且不能带static
// 默认构造函数
Man::Man() {
manCount++; // 静态数据成员可以被对象方法访问到
}
// 析构函数
Man::~Man() {
}
// 返回manCount
int Man::getCount() {
return manCount;
}
main.cpp
#include <iostream>
#include "../include/Man.h"
using namespace std;
int main() {
Man man1;
Man man2;
cout << man2.getCount() << endl;
return 0;
}
输入、输出:
➜ code ./a
2
➜ code
总结:
1、静态成员数据声明的时候不允许初始化,初始化需要在实现文件中去。
2、静态成员数据如果被const修饰,那么可以在声明中去初始化,但是需要C++11标准支持。被修饰后无法再更改。
3、所有对象成员函数都可以访问静态成员变量,但是却不属于某个对象而是属于整个类。
2、使用全局变量去实现
代码:
// man.h
#ifndef _MAN_H_
#define _MAN_H_
extern int Num; // 外部声明
class Man {
public:
Man(); // 默认构造函数
~Man(); // 析构函数
int getCount();
private:
static int manCount; // 静态成员用来统计创建的对象
// static int manCount = 0; static静态变量不能在这里初始化
};
#endif
// Man.cpp
#include "../include/Man.h"
int Num = 0; // 全局变量初始化
int Man::manCount = 0; // 静态成员数据在实现中初始化,而且不能带static
// 默认构造函数
Man::Man() {
manCount++; // 静态数据成员可以被对象方法访问到
Num++; // 全局变量实现
}
// 析构函数
Man::~Man() {
}
// 返回manCount
int Man::getCount() {
return manCount;
}
// main.cpp
#include <iostream>
#include "../include/Man.h"
using namespace std;
int main() {
Man man1;
Man man2;
cout << man2.getCount() << endl;
cout << Num << endl;
return 0;
}
输入、输出;
➜ code ./a
2
2
➜ code
静态成员函数
上面的静态成员数据的访问,都是通过对象函数去访问的。那么我们一定要创建个对象,然后在去访问到这个静态数据吗?这样就背离初衷了。C++中提供了静态成员方法,可以通过它去访问静态成员数据。它也和静态成员数据一样是属于类的,每个对象都可以访问到它,但是它不是属于某个对象的。
// Man.h
#ifndef _MAN_H_
#define _MAN_H_
extern int Num; // 外部声明
class Man {
public:
Man(); // 默认构造函数
~Man(); // 析构函数
int getCount();
static int GetCount(); // 静态成员函数
private:
int c = 0;
static int manCount; // 静态成员用来统计创建的对象
// static int manCount = 0; static静态变量不能在这里初始化
};
#endif
// Man.cpp
#include "../include/Man.h"
int Num = 0; // 全局变量初始化
int Man::manCount = 0; // 静态成员数据在实现中初始化,而且不能带static
// 默认构造函数
Man::Man() {
manCount++; // 静态数据成员可以被对象方法访问到
Num++; // 全局变量实现
}
// 析构函数
Man::~Man() {
}
// 返回manCount
int Man::getCount() {
return manCount;
}
// 静态成员函数和静态成员数据一样实现的时候不能加static
int Man::GetCount() {
// c = 12; 静态成员函数不能访问对象成员数据
// getCount(); 静态成员函数不能访问对象成员方法
return manCount;
}
//main.cpp
#include <iostream>
#include "../include/Man.h"
using namespace std;
int main() {
Man man1;
Man man2;
// 通过对象方法访问静态成员数据
cout << man2.getCount() << endl;
//访问全局变量
cout << Num << endl;
// 通过类名来访问静态成员函数
cout << Man::GetCount() << endl;
// 通过对象来访问静态方法
cout << man2.GetCount() << endl;
return 0;
}
输入、输出:
➜ code ./a
2
2
2
2
➜ code
总结:
1、静态成员函数可以通过类名、对象来访问
2、静态成员函数不可以访问对象的数据成员和成员函数
3、需要特别注意的时候静态成员方法不可以使用this指针