单例模式
单例模式:设计模式的一种,保证某个类永远只创建一个对象
- 构造函数\析构函数 私有化
- 定义一个私有的static成员变量指向唯一的那个单例对象(Rocket* m_rocket)
- 提供一个公共的访问单例对象的接口(shareRocket())
class Rocket {
private:
static Rocket* m_rocket;
Rocket() {}
public:
static Rocket* shareRocket() {
//注意考虑多线程安全问题
if (m_rocket==NULL)
{
m_rocket = new Rocket();
}
return m_rocket;
}
void run() {
cout << "run()" << endl;
}
};
Rocket* Rocket::m_rocket = NULL;
int main() {
Rocket* p = Rocket::shareRocket();
Rocket* p1 = Rocket::shareRocket();
Rocket* p2 = Rocket::shareRocket();
Rocket* p3 = Rocket::shareRocket();
cout << p << endl;
cout << p1 << endl;
cout << p2 << endl;
cout << p3 << endl;
p->run();
return 0;
}
当你需要销毁掉堆里的单例对象时,也需要在类中写一个公共接口
static void deleteRocket() {
//需要考虑多线程问题
if (m_rocket != NULL)
{
delete m_rocket;
m_rocket = NULL;//不赋值NULL可以会成野指针。使得重新申请单例对象时出现错误
//if(m_rocket==NULL)会不成立
}
}
为了防止外部直接delete p;而不去通过接口deleteRocket()删除,推荐把析构函数也私有化,完整代码如下:
#include<iostream>
using namespace std;
/*
单例模式:设计模式的一种,保证某个类永远只创建一个对象
1、构造函数\析构函数私有化
2、定义一个私有的static成员变量指向唯一的那个单例对象
3、提供一个公共的访问单例对象的接口
*/
class Rocket {
private:
static Rocket* m_rocket;
Rocket() {}
~Rocket(){}
public:
static Rocket* shareRocket() {
//注意考虑多线程安全问题
if (m_rocket==NULL)
{
m_rocket = new Rocket();
}
return m_rocket;
}
static void deleteRocket() {
if (m_rocket != NULL)
{
delete m_rocket;
m_rocket = NULL;
}
}
void run() {
cout << "run()" << endl;
}
};
Rocket* Rocket::m_rocket = NULL;
int main() {
Rocket* p = Rocket::shareRocket();
Rocket* p1 = Rocket::shareRocket();
Rocket* p2 = Rocket::shareRocket();
Rocket* p3 = Rocket::shareRocket();
cout << p << endl;
cout << p1 << endl;
cout << p2 << endl;
cout << p3 << endl;
p->run();
Rocket::deleteRocket();
return 0;
}
const成员
const成员:被const修饰的成员变量、非静态成员函数
const成员变量
- 必须初始化(类内部初始化),可以在声明的时候直接初始化赋值
- 非static的const成员变量还可以在初始化列表冲初始化
const成员函数
- const关键字写在参数列表后面,函数的声明和实现都必须带const
- 内部不能修改非static成员变量
- 内部只能调用const成员函数、static成员函数
- 非const成员函数可以调用const成员函数
#include <iostream>
using namespace std;
class Car
{
int m_price;
void run() const {
cout << "run()" << endl;
m_price = 0;//error
}
};
int main() {
return 0;
}
引用类型成员
- 引用类型成员变量必须i初始化(不考虑static情况)
- 在声明的时候直接初始化
- 通过初始化列表初始化
拷贝构造函数
- 拷贝构造函数是构造函数的一种
- 当利用已存在的对象创建一个新对象是(类似于拷贝),就会调用新对象的拷贝函数进行初始化
#include <iostream>
using namespace std;
class Car {
int m_price;
int m_length;
public:
Car(int price = 0, int length = 0) :m_price(price), m_length(length) {
cout << "Car(int price = 0, int length = 0) :m_price(price)" << endl;
}
//拷贝构造函数
Car(const Car& car):m_price(car.m_price),m_length(car.m_length) {
cout << "const Car& car" << endl;
}
void display() {
cout << "price=" << m_price << ",length=" << m_length << endl;
}
};
int main() {
Car car1;
Car car2(100, 200);
//拷贝构造函数,利用已经存在的car2对象创建了一个car3对象
//car3初始化时会调用拷贝构造函数
Car car3(car2);
car3.display();
return 0;
}
浅拷贝、深拷贝
编译器默认的提供的拷贝是浅拷贝(shallow copy)
- 将一个对象中所有成员变量的值拷贝到另一个对象
- 如果某个成员变量是个指针,只会拷贝指针中存储的地址值,并不会拷贝指针指向的内存空间
- 可能会导致堆空间多次free的问题
如果需要实现深拷贝(deep copy),就需要自定义拷贝构造函数
- 将指针类型的成员变量所指向的内存空间,拷贝到新的内存空间
下面这个例子是说浅拷贝导致了堆空间的变量指向了栈空间,不安全
#include<iostream>
using namespace std;
class Car {
int m_price;
char* m_name;
public:
Car(int price = 0, char* name = NULL):m_price(price),m_name(name) {}
void display() {
cout << "price is " << m_price << ",name is " <<m_name<< endl;
}
};
int main() {
const char* name = "bmw";
char name2[] = { 'b','m','w','\0' };
cout << name2 << endl;
cout << strlen(name) << endl;
Car *car = new Car(100, name2);
car->display();
return 0;
}
深拷贝,连同所指向的内存空间也拷贝了
#include<iostream>
using namespace std;
class Car {
int m_price;
char* m_name;
public:
Car(int price = 0, const char* name = NULL) :m_price(price){
if (name == NULL) return;
//申请新的堆空间
m_name = new char[strlen(name) + 1]{};
//拷贝字符串数据到新的堆空间
strcpy(m_name, name);
}
~Car() {
if (m_name == NULL) return;
delete m_name;
m_name = NULL;
}
void display() {
cout << "price is " << m_price << ",name is " << m_name << endl;
}
};
int main() {
const char* name = "bmw";
char name2[] = { 'b','m','w','\0' };
cout << name2 << endl;
cout << strlen(name) << endl;
Car* car = new Car(100, name);
car->display();
return 0;
}