1.拷贝构造
浅拷贝问题:编译器默认提供拷贝构造,是一个拷贝
1.当类中有指针成员并new了一个空间,会导致多次回收,程序崩溃
2.当类中有指针成员并new了一个空间,当用一个对象修改指针指向空间的值,其他对象使用的是修改之后的值,导致程序逻辑错误
解决浅拷贝的问题
1.需要手动重构拷贝构造函数实现深拷贝(为里面的指针成员单独开辟一个空间,并将指针的值传递过来
2.避免浅拷贝的发生,函数尽量使用引用或者指针
拷贝构造函数:函数名为当前名,参数当前类对象的引用
编译器默认提供的函数体代码不为空,参数对象里的成员给this对象中的成员依次初始化
如果手动重构了拷贝构造函数,编译器不在提供默认的拷贝构造
class CTest {
public:
int m_a;
int* m_p;
CTest(int a ) {//构造函数只有一个参数,或多个参数且有默认值
m_a = a;
m_p = new int(1);
}
CTest(const CTest& tst)
{
m_a = tst.m_a;
//this->m_p = tst.m_p;浅拷贝会出问题
if (tst.m_p) {//这种方法是深拷贝,自己又建立了一个新的空间
this->m_p = new int(*tst.m_p);
}
else {
this->m_p = nullptr;
}
}
~CTest() {
delete m_p;//浅拷贝构造,执行之后会有多次的回收,第一次已经被回收了,第二次回收就会出问题
m_p = nullptr;
}
};
void show(CTest &tst) {
}
int main() {
CTest tst(10);
/*
*EXPLICIT CTest(int a ) 禁止使用隐式转换
* m_a = a;
*/
CTest tst2(tst);//调用拷贝构造
*tst.m_p = 100;
cout << *tst.m_p << " " << *tst2.m_p << endl;//浅拷贝:修改当前值,也会改变浅拷贝对的值||||深拷贝:不能修改当前的值
show(tst);
system("pause");
return 0;
2.隐式类型转换
/*
类中会存在默认的operator=(const CTest &),编译器会默认给提供
*/
/*
空类中,有哪些默认的函数
默认无参数构造函数
默认的析构函数
拷贝构造
默认的operator=(const ctest &)
*/
#include<iostream>
using namespace std;
class CTEST {
public:
int m_a;
int* m_p;
CTEST(int a)
{
m_a = a;
m_p = new int(10);
}
CTEST& operator =(const CTEST& tst) {
cout << "operator =" << endl;
this->m_a = tst.m_a;
this->m_p = tst.m_p;
return *this;
}
~CTEST()
{
if (m_p)
{
delete m_p;
}
}
};
int main() {
CTEST tst1(10);
/*
CTEST tst3=20;
tst3=40;
*/
system("pause");
return 0;
}
3.设计模式
1.sington
/*
* 设计模式:前任总结的经验规则,经过分类,编排形成而一套针对于程序设计的经验总结
* 它是针对某些重复出现的问题而设计的一套成功有效的解决方案
* 3打雷,创建型模式,结构型模式,行为型模式,23种
*
* 分类:懒汉式,饿汉式
* 懒汉式:第一次使用该实例时,在创建
*
* 饿汉式:程序创建之初,不管用不用这个实例,都要提前创建好
*/
/*
单例模式Sington
1.类最多智能创建一个实例
2.类能够自主的创建实例
3.能够向整个系统提供全局的访问接口访问实例
优点:
1.提供了严格的唯一的实力的创建,访问销毁,提高了安全性
2.节约系统支援
*/
(1)第一种方法--过度
class CSington {
private:
//static int m_count;//表明对该类所有对象这个数据成员都只有一个实例。即该实例归 所有对象共有。
static CSington* m_pSin;
CSington()
{
m_a = 10;
}
CSington(const CSington& sin) {//防止产生拷贝构造,创建新对象
m_a = sin.m_a;
}
~CSington()//防止CSington *pys=new CSington(*psin),创造出新对象
{
}
public:
static CSington* GetSinton() {
if (m_pSin) {//替换掉了if (m_count >= 1)
return m_pSin;
}
//m_count++;
m_pSin = new CSington;
return m_pSin;
}
static void DestroySington(CSington*& pSin) {
if (m_pSin) {//一次性删永久了,其他指针都无法用了
delete m_pSin;
m_pSin = nullptr;
}
pSin = nullptr;
}
public:
int m_a;
};
//int CSington::m_count = 0;//静态成员进行初始化.利用m_pSin替换
CSington* CSington::m_pSin=nullptr;
int main01()
{
CSington* pSin1 = CSington::GetSinton();
CSington* pSin2 = CSington::GetSinton();
CSington::DestroySington(pSin1);
if (pSin1) {
cout << pSin1->m_a <<"psin1"<< endl;
}
if (pSin2) {
cout << pSin2->m_a << "psin2" << endl;
}
return 0;
}
(2)第二种方法---直接
这种方法就要比前一种方便很多,步骤也是简洁了很多
class CSington {
private:
static CSington* m_pSin;
CSington()
{
m_a = 10;
}
CSington(const CSington& sin) {//防止产生拷贝构造,创建新对象
m_a = sin.m_a;
}
~CSington()//防止CSington *pys=new CSington(*psin),创造出新对象
{
}
public:
static CSington* GetSinton() {//比较与第一张方法,更简单,并且解决了destroy一次性解决所有指针的情况
static CSington sin;//静态成员对象:只能创建出一个对象,第二个创建不出来,从程序开始生成,一直保留到程旭结尾
return &sin;
}
public:
int m_a;
};
int main02()
{
CSington* pSin1 = CSington::GetSinton();
CSington* pSin2 = CSington::GetSinton();
if (pSin1) {
cout << pSin1->m_a << "psin1" << endl;
}
if (pSin2) {
cout << pSin2->m_a << "psin2" << endl;
}
return 0;
}
(3)饿汉式
#include <iostream>
using namespace std;
/*
饿汉式
*/
class CSington {
private:
static CSington sin;
static CSington* m_pSin;
CSington()
{
m_a = 10;
}
CSington(const CSington& sin) {//防止产生拷贝构造,创建新对象
m_a = sin.m_a;
}
~CSington()//防止CSington *pys=new CSington(*psin),创造出新对象
{
}
public:
static CSington* GetSinton() {//比较与第一张方法,更简单,并且解决了destroy一次性解决所有指针的情况
return &sin;
}
public:
int m_a;
};
CSington CSington::sin;
int main()
{
CSington* pSin1 = CSington::GetSinton();
CSington* pSin2 = CSington::GetSinton();
if (pSin1) {
cout << pSin1->m_a << "psin1" << endl;
}
if (pSin2) {
cout << pSin2->m_a << "psin2" << endl;
}
return 0;
}
2.factory
#include<iostream>
#include<string>
using namespace std;
class CEngine{
public:
virtual void working()=0;
};
class CEngine2L:public CEngine{
public:
virtual void working(){
cout<<"2.0 自然吸气发动机正在工作,wu~wu~wu~"<<endl;
}
};
class CEngine2T:public CEngine{
public:
virtual void working(){
cout<<"2.0 涡轮增压发动机正在工作,weng~weng~weng"<<endl;
}
};
class CCar{
public:
CEngine * m_pEngine; //父类发动机指针
CCar(){
m_pEngine = new CEngine2L;
}
CCar(string type){
if(type== "2.0L"){
m_pEngine = new CEngine2L;
}else if(type== "2.0T"){
m_pEngine = new CEngine2T;
}else{
m_pEngine = nullptr;
}
}
void driving(){
if(m_pEngine){
m_pEngine->working();
cout<<"我的小汽车,正在疯狂的行使中..."<<endl;
}
}
};
int main(){
CCar bmw;
bmw.driving();
CCar benz("2.0L");
benz.driving();
system("pause");
return 0;
}
最后的工程例子,设计一个工厂的类,里面在设计出对应需要的功能,把这个作为一个大类,在定义需要的车,利用指针的传递,将车所需要的类型传到工厂中
#include<iostream>
#include<string>
using namespace std;
class CEngine {
public:
virtual void working() = 0;
};
class CEngine2L :public CEngine {
public:
virtual void working() {
cout << "2.0 自然吸气发动机正在工作,wu~wu~wu~" << endl;
}
};
class CEngine2T :public CEngine {
public:
virtual void working() {
cout << "2.0 涡轮增压发动机正在工作,weng~weng~weng" << endl;
}
};
class GearBox {
public:
virtual void working() = 0;
};
class GearBoxSelfcontrol :public GearBox {
public:
virtual void working() {
cout << "自动档变速在工作" << endl;
}
};
class GearBoxManual :public GearBox {
public:
virtual void working() {
cout << "手动挡变速在工作" << endl;
}
};
class CfactoryGearBox
{
public:
virtual GearBox* CreateGearBox() = 0;
};
class CFactorySeifControl :public Cfactory {
virtual GearBox* CreateGearBox() {
return new GearBoxSelfcontrol;
}
};
class CfactoryManual :public Cfactory {
virtual GearBox* CreateGearBox() {
return new GearBoxManual;
}
};
class Cfactory
{
public:
virtual CEngine* CreateEngune() = 0;
};
class CFactory2L :public Cfactory {
virtual CEngine* CreateEngune() {
return new CEngine2L;
}
};
class CFactory2T :public Cfactory {
virtual CEngine* CreateEngune() {
return new CEngine2T;
}
};
class CCar {
public:
CEngine* m_pEngine; //父类发动机指针
CCar(Cfactory* pfac) {
if (pfac) {
m_pEngine = pfac->CreateEngune();
}
else
{
m_pEngine = nullptr;
}
}
void driving() {
if (m_pEngine) {
m_pEngine->working();
cout << "我的小汽车,正在疯狂的行使中..." << endl;
}
}
};
int main() {
return 0;
}