拷贝构造函数
// 空类中编译器会提供一个默认的特殊的构造函数:拷贝构造函数
// 拷贝构造函数 函数名 当前类名 参数const 当前类的引用
// 拷贝构造函数在用当前类的一个对象给另一个对象初始化的时候时被调用
// 参数中对象给this对象成员依次初始化
浅拷贝问题
- 如果类中成员存在指针变量且new分配空间,调用拷贝构造函数的时候是值拷贝(地址拷贝)的过程,因此在析构回收空间时,同一个地址空间会被delete多次,导致程序崩溃。
- 多个对象指针指向同一个空间,其一个对象修改里面的值,其他对象使用后的值是修改后的。如果实际确实需要多个对象共享,也不建议使用该方式,可以使用static静态成员变量。
#include <iostream>
using namespace std;
class CTest
{
public:
int m_a;
int* m_p;
public:
CTest() {
m_a = 10;
m_p = new int(20);
}
CTest(int a) {
m_a = a;
}
~CTest() {
if (m_p) {
delete m_p;
m_p = NULL;
}
}
};
int main() {
CTest tst;
CTest tst1(tst);
*tst1.m_p = 50;
cout << *tst.m_p << endl;
system("pause");
return 0;
}
解决浅拷贝问题:深拷贝
CTest(const CTest& tst) {
this->m_a = tst.m_a;
if (tst.m_p)
{
this->m_p = new int(*tst.m_p);
}
else {
this->m_p = NULL;
}
}
#include <iostream>
using namespace std;
class CTest
{
public:
int m_a;
int* m_p;
public:
CTest() {
m_a = 10;
m_p = new int(20);
}
CTest(int a) {
m_a = 20;
m_p = NULL;
}
CTest(const CTest& tst) {
this->m_a = tst.m_a;
if (tst.m_p)
{
this->m_p = new int(*tst.m_p);
}
else {
this->m_p = NULL;
}
}
~CTest() {
if (m_p) {
delete m_p;
m_p = NULL;
}
};
int main() {
CTest tst1;
CTest tst2(tst1);
CTest tst3(10);
CTest tst4(tst3);
system("pause");
return 0;
}
operator=(重载等号函数)
解决浅拷贝问题:深拷贝
const CTest& operator=(const CTest& tst) {
this->m_a = tst.m_a;
if (tst.m_p)
{
if (this->m_p)
{
*this->m_p = *tst.m_p;
}
else {
this->m_p = new int(*tst.m_p);
}
}
else {
if (this->m_p)
{
delete this->m_p;
this->m_p = NULL;
}
else {
this->m_p = tst.m_p;
}
}
return *this;
}
#include <iostream>
using namespace std;
class CTest
{
public:
int m_a;
int* m_p;
public:
CTest() {
m_a = 10;
m_p = NULL;
}
CTest(int a) {
m_a = a;
m_p = new int(30);
}
int operator=(int a) {
m_a = a;
return m_a;
}
const CTest& operator=(const CTest& tst) {
this->m_a = tst.m_a;
if (tst.m_p)
{
if (this->m_p)
{
*this->m_p = *tst.m_p;
}
else {
this->m_p = new int(*tst.m_p);
}
}
else {
if (this->m_p)
{
delete this->m_p;
this->m_p = NULL;
}
else {
this->m_p = tst.m_p;
}
}
return *this;
}
~CTest() {
if (m_p)
{
delete m_p;
m_p = NULL;
}
}
};
int main() {
CTest tst1;
CTest tst2;
tst1 = tst2;
CTest tst3(20);
tst2 = tst3;
CTest tst4(40);
tst4 = tst3;
CTest tst5;
tst5 = tst4;
system("pause");
return 0;
}
整理:空类中默认的函数(4个)
- 默认无参构造函数
- 默认析构函数
- 默认拷贝构造函数
- 默认operator=(重载等号操作符)
设计模式之单例模式
- 1.当前类 有且只有 一个实例(对象)
----->类外不能定义对象 只能使用类内定义的一个对象 - 2.能够自主创建这个实例(而不是调用者去创建实例)
- 3.向全局开放这个实例
懒汉式
- 要用到的时候再去创建唯一实例(时间换空间的做法,节省空间但消耗时间)
- 多线程下要加锁,造成阻塞等待,只让一个线程进入m_pObjec = new CObject;的部分。
#include <iostream>
using namespace std;
class CObject
{
public:
int m_a;
private:
static CObject* m_pObjec;
private:
CObject() {
m_a = 10;
}
CObject(const CObject& obj) {
this->m_a = obj.m_a;
}
~CObject() {
}
public:
static CObject* GetInstance()
{
if (m_pObjec)
{
return m_pObjec;
}
m_pObjec = new CObject;
return m_pObjec;
}
static void Destory(CObject*& p) {
if (m_pObjec) {
delete m_pObjec;
m_pObjec = NULL;
}
p = NULL;
}
};
CObject* CObject::m_pObjec = NULL;
int main() {
CObject* pObject1 = CObject::GetInstance();
CObject* pObject2 = CObject::GetInstance();
pObject1->m_a = 20;
cout << pObject2->m_a << endl;
CObject::Destory(pObject1);
CObject::Destory(pObject2);
if (pObject2)
{
cout << pObject2->m_a << endl;
}
system("pause");
return 0;
}
饥汉式
- 不管用与否,程序创建之初就把唯一实例创建出来(空间换时间的做法,不需要现new节省了时间,但从始至终一直占用空间)
- 多线程下没问题。CObject* CObject::m_pObjec = new CObject;只会在程序运行初的编译期运行一次。
#include <iostream>
using namespace std;
class CObject
{
public:
int m_a;
private:
static CObject* m_pObjec;
private:
CObject() {
m_a = 10;
}
CObject(const CObject& obj) {
this->m_a = obj.m_a;
}
~CObject() {
}
public:
static CObject* GetInstance() {
return m_pObjec;
}
};
CObject* CObject::m_pObjec = new CObject;
int main(){
CObject* p1 = CObject::GetInstance();
CObject* p2 = CObject::GetInstance();
p1->m_a = 30;
cout << p2->m_a << endl;
system("pause");
return 0;
}
设计模式之模板方法模式
- 将不变的流程(步骤)和可变的实现(细节)分开,将公共的流程抽离到父类形成模板,具体的实现利用多态在子类中完成实现。
#include <iostream>
using namespace std;
class CPeople
{
public:
virtual void EatBehavior() = 0;
virtual void EatSytle() = 0;
void eat() {
cout << "1.盛一碗饭" << endl;
EatBehavior();
EatSytle();
cout << "4.放嘴里嚼" << endl;
cout << "5.吞肚子里" << endl;
cout << "6.吃完饭了" << endl;
}
};
class CChina:public CPeople
{
public:
void EatBehavior() {
cout << "2.端起来碗" << endl;
}
void EatSytle() {
cout << "3.筷子扒拉" << endl;
}
};
class CAmerican :public CPeople
{
public:
void EatBehavior() {
cout << "2.嘴靠上去" << endl;
}
void EatSytle() {
cout << "3.刀叉扒拉" << endl;
}
};
class CIndian :public CPeople
{
public:
void EatBehavior() {
cout << "2.嘴靠上去" << endl;
}
void EatSytle() {
cout << "3.用手抓饭" << endl;
}
};
int main() {
CPeople* pPeo1 = new CChina;
pPeo1->eat();
CPeople* pPeo2 = new CAmerican;
pPeo2->eat();
CPeople* pPeo3 = new CIndian;
pPeo3->eat();
system("pause");
return 0;
}