C++ static 重要知识点
- 1.静态成员变量
- 定义
- 2.静态成员函数
- 3. 静态成员经典应用 – 单例模式
1.静态成员变量
定义
静态成员:被static修饰的成员变量(成员函数);
只占用一份内存。
静态成员变量必须初始化
- 如何访问?
答:可以通过对象(对象.静态成员)、对象指针(对象->静态成员)、类访问(类名::静态成员)
- 静态成员变量
答:
1.存储在数据段(全局区,类似于全局变量),整个程序运行过程中只有一份内存
2.必须初始化,必须在类外面初始化,初始化时不能带static,如果类的声明和实现分离(在实现.cpp中初始化)
3.对比全局变量,它可以设定访问权限(public、 protected、 private),达到局部共享的目的
- 怎么初始化静态成员变量?
必须在类外面初始化静态成员变量;
静态成员变量是不依赖于类存在的,只占用一份内存。
class Car {
public:
static int m_price;
};
// 在类外面初始化成员变量
int Car::m_price = 0;
- 访问静态成员代码:
int main() {
// 对象访问
Car car1;
car1.m_age = 1;
car1.m_price = 2;
Car car2;
car2.m_price = 200;
Car car3;
car3.m_price = 300;
// 指针访问
Car *p = new Car();
p->m_price = 400;
delete p;
// 类名直接访问
cout << Car::m_price << endl;
getchar();
return 0;
}
2.静态成员函数
- 访问(和访问静态成员变量一样):
Car car;
car.run(); // 对象
Car *p = &car;
p->run(); // 指针
Car::run(); // 直接通过类
- 静态成员函数
1.内部不能使用this指针(this指针只能用在非静态成员函数内部)
2.不能是虚函数(虚函数只能是非静态成员函数)
3.静态成员函数内部不能访问非静态成员变量\函数,只能访问静态成员变量\函数
4.非静态成员函数内部可以访问静态成员变量\函数
5.构造函数、析构函数不能是静态(构造和析构只能通过对象去调用,所以不能是静态)
6.当声明和实现分离时,实现部分不能带static
7.可以直接访问静态成员函数,这样可以不创建对象,直接去访问静态成员函数。
3. 静态成员经典应用 – 单例模式
单例模式:设计模式的一种,保证某个类永远只创建一个对象;
步骤:
1.构造函数\析构函数私有化
2.定义一个私有的static成员变量指向唯一的那个单例对象
3.提供一个公共的访问单例对象的接口
- 构造函数/析构函数私有化
class Rocket {
private:
Rocket() {}
~Rocket() {}
};
- 定义一个私有的static成员变量指向唯一的那个单例对象
class Rocket {
private:
Rocket() {}
static Rocket *ms_rocket; // 静态成员变量记得初始化!
~Rocket() {}
public:
};
Rocket *Rocket::ms_rocket = NULL; // 初始化静态成员变量
- 提供一个公共的访问单例对象的接口
class Rocket {
private:
Rocket() {}
static Rocket *ms_rocket; // 静态成员变量记得初始化!
~Rocket() {}
public:
// 携程静态成员函数,外面想要用Rocket创建对象的话,调用sharedRocket,
static Rocket *sharedRocket() {
// 这里要考虑多线程安全
if (ms_rocket == NULL) {
// 在堆空间申请一个内存,去访问
ms_rocket = new Rocket();
}
return ms_rocket;
}
};
Rocket *Rocket::ms_rocket = NULL; // 初始化静态成员变量
int main() {
Rocket *p = Rocket::sharedRocket();
}
注解:这里就是说只有第一次访问的时候是有效的,后面都会直接 return ms_rocket
这样就能保证Rocket类只能创建一个对象(创建对象写在了 private 中)
public:
// 携程静态成员函数,外面想要用Rocket创建对象的话,调用sharedRocket,
static Rocket *sharedRocket() {
// 这里要考虑多线程安全
if (ms_rocket == NULL) {
// 在堆空间申请一个内存,去访问
ms_rocket = new Rocket();
}
return ms_rocket;
}