1 静态局部变量
使用static关键字修饰类中的局部变量,该变量为静态局部变量
静态局部变量所在的函数第一次调用时,静态局部变量创建并初始化
后续此函数被任何该类的对象调用时,都会直接使用之前创建的静态局部变量
即同类的所有对象共用这一份静态局部变量
静态局部变量一旦创建只有在程序运行结束后才会销毁。
静态局部变量demo
#include <iostream>
using namespace std;
class Test
{
public:
void test_static()
{
static int a1 = 0; // 静态局部变量,创建后只有在程序结束后才会销毁
int a2 = 0; // 局部变量,生命周期仅在9-14行
cout << ++a1 << " " << ++a2 << endl;
cout << &a1 << " " << &a2 << endl;
}
};
int main()
{
Test t1; // 对象t1
Test t2; // 对象t2
t1.test_static();
t1.test_static();
t2.test_static();
return 0;
}
运行结果
1 1
0x408048 0x61fe6c
2 1 // 静态局部变量一直存在,可以被改变;非静态局部变量用完一次就嘎
0x408048 0x61fe6c // 实质上静态局部变量的地址没变,局部变量只是在改地址重新创建
3 1 // 同类的所有对象共用这一份静态局部变量
0x408048 0x61fe6c
2 静态成员变量
使用static关键字修饰类中的成员变量,表示该变量为静态成员变量
静态成员变量在程序开始执行时创建,在程序结束执行时销毁
因此:有了静态成员变量后,一个类没有对象也有存在的意义,不用对象也能调用
与静态局部变量相同的是,静态成员变量也是同类对象共用的
需要注意的是,非const静态成员变量必须类内声明,类外初始化
静态成员变量demo
#include <iostream>
using namespace std;
class Test
{
public:
static int a1; // 静态成员变量 类内声明
// static int a1 = 1; 报错,编译器不允许
// static const int a1 = 1; 增加const修饰可以编译通过
int a2 = 1;
};
int Test::a1 = 1; // 静态成员变量 类外初始化
int main()
{
// 为了代码的可读性,更推荐使用类名::的方式调用静态成员变量
cout << ++Test::a1 << " " << &Test::a1 << endl; // 2 0x408004
Test t1;
cout << ++t1.a1 << " " << &t1.a1 << endl; // 3 0x408004
cout << ++t1.a2 << " " << &t1.a2 << endl; // 2 0x61fe8c
Test t2;
cout << ++t2.a1 << " " << &t2.a1 << endl; // 4 0x408004
cout << ++t2.a2 << " " << &t2.a2 << endl; // 2 0x61fe88
return 0;
}
3 静态成员函数
使用static关键字修饰类中的成员函数,表示该函数为静态成员函数
1静态成员函数没有this指针,无法访问同类中的非静态成员,可访问静态成员
2成员函数可以访问静态成员
3声明定义分离,只需在声明处使用static
4推荐使用类名::的方式调用
代码示例
#include <iostream>
using namespace std;
class Test
{
private:
static string str; // 静态成员变量 类内声明
static void show(); // 静态成员函数show 类内声明
public:
static void print(); // 静态成员函数print 类内声明
};
// 静态成员变量在程序开始执行时创建,同类对象共用
string Test::str = "静态成员变量"; // 静态成员变量 类外初始化
void Test::show() // 静态成员函数show 类外定义
{
cout << "静态成员函数2" << endl;
}
void Test::print() // 静态成员函数print 类外定义
{
cout << "静态成员函数1" << endl;
// cout << this << endl; 错误,静态成员函数不可用
cout << str << " ";
show();
}
int main()
{
// 推荐使用类名::调用静态成员函数
Test::print();
cout << "------------------------" << endl;
Test t;
t.print();
return 0;
}
4 设计模式——单例模式
设计模式是一套被反复使用的、多数人知晓的、经过分类的代码设计总结
其中单例模式是设计模式中最基础的模式之一,此模式主要靠static关键字来实现
单例模式即单实例模式,用这种模式设计的类可以保证在整个项目下只有一个对象
static结合指针
#include <iostream>
using namespace std;
class SingleTon
{
// 屏蔽构造函数,默认两个,构造函数与拷贝构造函数
private:
SingleTon(){}
SingleTon(const SingleTon&);
// 如果想要对外界开放销毁的功能,析构函数不能私有化
//~SingleTon(){}
// 写一个私有的对象instance(实例)
static SingleTon* instance; // 私有实例 类内声明
// 屏蔽构造后,重新公开静态接口获取对象
public:
// 普通成员函数需要对象来调用,静态成员函数不需要对象
static SingleTon* get_instance() // 获得堆内存单实例对象
{
if (instance == NULL)
instance = new SingleTon;
return instance;
}
// 首次调用该函数会new,再次调用会直接返回————全局只有一个对象
// 栈内存会手动创建和销毁
static void delete_instance() // 销毁堆内存单实例对象
{
if (instance != NULL)
{
delete instance;
instance = NULL;
}
}
};
SingleTon * SingleTon::instance = NULL; // 私有实例 类外定义
int main()
{
SingleTon* s1 = SingleTon::get_instance();
SingleTon* s2 = SingleTon::get_instance();
cout << s1 << " " << s2 << endl;
SingleTon::delete_instance(); // 给用户开启销毁功能,否则内存泄漏
cout << SingleTon::get_instance() << endl;
// 虽然地址一样,但不是之前的对象
return 0;
}
程序运行结果
0x1000fc0
0x1000fc0
0x1000fc0
static结合引用
#include <iostream>
using namespace std;
class SingleTon
{
// 屏蔽构造函数,默认两个,构造函数与拷贝构造函数
private:
SingleTon(){}
SingleTon(const SingleTon&);
~SingleTon(){}
// 屏蔽构造后,重新公开静态接口获取对象
public:
// 普通成员函数需要对象来调用,静态成员函数不需要对象
// 引用可以防止副本产生,不会产生新对象
static SingleTon& get_instance() // 获得栈内存单实例对象
{
static SingleTon instance;
// 栈内存静态局部变量,只有第一次调用时才会创建,后面直接使用,程序终止后销毁
// 不调用get_instance就不会产生,不会占用内存
return instance;
}
};
int main()
{
SingleTon& s1 = SingleTon::get_instance();
SingleTon& s2 = SingleTon::get_instance();
cout << &s1 << endl;
cout << &s2 << endl;
return 0;
}
程序运行结果
0x408050
0x408050