单例模式
单例模式:设计模式的一种,保证某个类永远只创建一个对象
- 构造函数\析构函数 私有化
- 定义一个私有的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;
}