7.9 c++

1.remove

remove(first, last, val); //删除first到last之间所有值为val的元素
remove只是通过迭代器的指针向后移动来删除,将没有被删除的元素放在链表的前面,并返回一个指向新的位置的迭代器。由于remove()函数不是vector成员函数,因此不能调整vector容器的长度。(对vector来说)remove()函数并不是真正的删除,要想真正删除元素则可以使用erase()或者resize()函数。

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;



void printV(vector<int>& v){
    int size = v.size();
    printf(":--------------------------------------\n");
    printf("size=%d\n", size);
    auto it = v.begin();
    for(; it != v.end();it++){
        cout << *it << " ";
    }
    printf("\n--------------------------------------;\n");
}

int main(){
	vector<int>v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);
	v1.push_back(11);
	v1.push_back(16);
	printV(v1);
	v1.erase(remove(v1.begin(),v1.end(),3));
	printV(v1);
	//如果想删除必须加erase
	return 0;
}

:--------------------------------------
size=6
1 3 5 7 11 16
--------------------------------------;
:--------------------------------------
size=5
1 5 7 11 16
--------------------------------------;

2.remove_if

函数原型:ForwardIterator remove_if (ForwardIterator first, ForwardIterator last,
UnaryPredicate pred);
简单的说就是:remove_if(first, last, pred) 从first到last中将满足条件pred的元素删除
这个函数就是按条件删除元素
remove_if的参数是迭代器,通过迭代器无法得到容器本身,而要删除容器内的元素只能通过容器的成员函数erase来进行,因此remove系列函数无法真正删除元素,只能把要删除的元素移到容器末尾并返回要被删除元素的迭代器,然后通过erase成员函数来真正删除。

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

void printV(vector<int>& v){
    int size = v.size();
    printf(":--------------------------------------\n");
    printf("size=%d\n", size);
    auto it = v.begin();
    for(; it != v.end();it++){
        cout << *it << " ";
    }
    printf("\n--------------------------------------;\n");
}
bool IfEqualThree(int ret) {
    return ret == 3;
}

int main() {
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    v.push_back(3);
    printV(v);
    v.erase(remove_if(v.begin(), v.end(), IfEqualThree), v.end());
    printV(v);
}

:--------------------------------------
size=7
1 2 3 3 4 5 3
--------------------------------------;
:--------------------------------------
size=4
1 2 4 5
--------------------------------------;

3.设计模式

设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
设计模式被分为三大类:创建型,结构型和行为型模式。

(1)单例模式

单例模式保证一个类只生成一个实例对象。也就是说在整个程序运行过程中,该类只有一个对象。
单例的设计步骤:
1.构造函数私有化
2.在类中定义一个静态指针,指向本类的的静态私有对象成员
3.提供一个全局的静态方法,用于获取上面生成的对象
(静态访问点)

单例分为懒汉式饿汉式,区别在于对象创建时间不同。懒汉式是在第一次使用对象时创建,而饿汉式则在程序启动时就将对象创建好,无论是否使用。

(1)饿汉式

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

class UserDAO{
	//1.私有化构造方法
	UserDAO(){}
	//2.生成一个静态的本类成员,并且私有的
	static UserDAO* dap;//静态的需要在类外赋值
	static int count;	
public:
	//3.提供一个共有的静态方法,用于获取上面的静态成员对象
	static UserDAO* getinstance(){
		count ++;
		return dap;
	}
	void release(){
		count--;
		if(count==0){
			delete dap;
			dap=NULL;//必须让dap指向NULL否则会指向别的地方
		}
	}
};

UserDAO* UserDAO::dap=new UserDAO;
int UserDAO::count=0;
int main(){
	UserDAO* dap1=UserDAO::getinstance();
	UserDAO* dap2=UserDAO::getinstance();
	UserDAO* dap3=UserDAO::getinstance();
	printf("dap1=%x\n",dap1);
	printf("dap2=%x\n",dap2);
	printf("dap3=%x\n",dap3);
	dap1->release();
	dap2->release();
	dap3->release();
	return 0;
}

dap1=1870c20
dap2=1870c20
dap3=1870c20

(2)懒汉式

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

class usermanage{
private:
	usermanage(){}
public:
	static usermanage* getinstanc(){
		if(m_instance==NULL){
			m_instance=new usermanage;
		}
		count++;
		return m_instance;
	}
	static void release(){
		count--;
		if(m_instance!=NULL&&count==0){
			delete m_instance;
			m_instance=NULL;
		}
	}

private:
	static usermanage* m_instance;
	static int count;
};

usermanage* usermanage::m_instance=NULL;
int usermanage::count=0;

int main(){
	usermanage* num1=usermanage::getinstanc();
	usermanage* num2=usermanage::getinstanc();
	if(num1=num2){
		cout<<"同一个对象"<<endl;
	}else{
		cout<<"不是同一个对象"<<endl;
	}
	num1->release();
	num2->release();
	return 0;
}

同一个对象

饿汉式在初始化对象的时候就创建了一个对象,而懒汉式则每次使用对象前都要判断该对象是否存在,不存在创建对象。

(3)关于多线程的问题
由于懒汉式在每次获取对象指针时都要进行判断,多线程下可能会导致对象被多次创建

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include<unistd.h>
using namespace std;

//懒汉式单例
class usermanage{
private:
	usermanage(){
		printf("构造函数被调用\n");
		sleep(5);
	}
	static int count;
	static usermanage* m_instance;
public:
	static usermanage* getinstance(){
		if(m_instance==NULL){
		m_instance=new usermanage;
	}
	count++;
	return m_instance;
	}

	static void release(){
		count--;
		if(m_instance!=NULL&&count==0){
			delete m_instance;
			m_instance=NULL;
		}
	}
};

usermanage* usermanage::m_instance=NULL;
int usermanage::count=0;

void* func(void* arg){
	usermanage* mu=usermanage::getinstance();
}

int main(){
	pthread_t id;
	for(int i=0;i<10;i++){
		pthread_create(&id,NULL,func,NULL);
		pthread_detach(id);//由系统来回收线程所占用资源。
	}

	pthread_exit(NULL);//主线程退出不影响其他进程运行
	return 0;

}

构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用
构造函数被调用

上面创建了10个线程后,10个线程同时去获取对象指针,这是对象还没有创建而构造函数又是一个很费时的操作,导致10个线程都去调用构造函数进行对象创建。
为了在多线程情况下正常运行,我们需要使用一些线程同步机制来控制对象的创建。

互斥锁

class usermanage{
private:
	usermanage(){
		printf("构造函数被调用\n");
		sleep(5);
	}
	static int count;
	static usermanage* m_instance;
	static pthread_mutex_t mutex;
public:
	static usermanage* getinstance(){
		pthread_mutex_lock(&mutex);//上锁
		if(m_instance==NULL){
		m_instance=new usermanage;
	}
	pthread_mutex_unlock(&mutex);//解锁
	count++;
	return m_instance;
	}

	static void release(){
		pthread_mutex_lock(&mutex);//上锁
		count--;
		if(m_instance!=NULL&&count==0){
			delete m_instance;
			m_instance=NULL;
		}
		pthread_mutex_unlock(&mutex);//解锁
	}
};

usermanage* usermanage::m_instance=NULL;
int usermanage::count=0;
pthread_mutex_t usermanage::mutex=PTHREAD_MUTEX_INITIALIZER;

这样修改之后,可以保证单例模式能够在多线程下正常使用。但是这里有一个不好的地方就是,在每次获取对象时都要进行上锁和解锁的操作,这会带来很大的开销。实际上,当对象创建出来后进行调用时已经不需要上锁和解锁的操作,我们可以进一步优化代码

static usermanage* getinstance(){
	if(m_instance==NULL){//增加一次判断,避免频繁的上锁和解锁
		pthread_mutex_lock(&mutex);//上锁
		if(m_instance==NULL){
			m_instance=new usermanage;
		}
		pthread_mutex_unlock(&mutex);//解锁
	}
	count++;
	return m_instance;
}
(2)工厂模式

(1)简单工厂模式
简单工厂也叫静态工厂,是一种由工厂对象决定创建出哪一种产品类的实例。
简单工厂模式中的各个角色如下:
1)工厂(Creator):负责创建所有实例的内部逻辑
2)抽象(Product):它是简单工厂所创建的所有对象的父类
3)具体产品(Concreate Product):它是简单工厂创建出来的具体产品

#include <iostream>
#include<string>
using namespace std;

class Operator{
public:
	virtual int getresult(int a,int b)=0;
};

class add:public Operator{
	int getresult(int a,int b){
		return a+b;
	}
};

class sub:public Operator{
	int getresult(int a,int b){
		return a-b;
	}
};

class factory{
public:
	Operator* createOperator(string name){
		Operator* opt=NULL;
		if(name=="加法"){
			opt=new add;
		}else if(name=="减法"){
			opt=new sub;
		}
		return opt;
	}
};

int main(){
	factory *fl=new factory;
	Operator *opt=fl->createOperator("加法");
	cout<<opt->getresult(10,4)<<endl;
	delete opt;


	opt=fl->createOperator("减法");
	cout<<opt->getresult(10,4)<<endl;
	delete opt;
	delete fl;

	return 0;
}

14
6

(2)工厂方法模式
在工厂方法中,核心的工厂不再负责所有产品的创建,而是将具体的创建工作交给子类去完成,工厂类成为一个抽象工厂角色,仅给出具体工厂必须实现的接口。
(1)抽象工厂(creator)角色:他是工厂方法模式的核心,任何工厂类都必须实现这个接口。
(2)具体工厂(concrete creator)角色:是抽象工厂的一个实现,负责实例化产品对象。
(3)抽象(product)角色:它是工厂方法模式所创建的所有对象的父类,负责描述所有实例所共有的接口。
(4)具体产品(concrete product)角色:它是工厂方法模式所创建的具体实例对象。

#include <iostream>
#include<string>
using namespace std;

class Operator{
public:
	virtual int getresult(int a,int b)=0;
};

class add:public Operator{
	int getresult(int a,int b){
		return a+b;
	}
};

class sub:public Operator{
	int getresult(int a,int b){
		return a-b;
	}
};

class obsfactory{
public:
	virtual Operator* createOperator()=0;
};

class addfactory:public obsfactory{
	Operator* createOperator()
	{
		Operator* opt=new add;
		return opt;
	}
};

class subfactory:public obsfactory{
	Operator* createOperator()
	{
		Operator* opt=new sub;
		return opt;
	}
};


int main(){
	obsfactory * oft=new addfactory;
	Operator* opt=oft->createOperator();
	cout<<"加法结果"<<opt->getresult(10,4)<<endl;

	delete oft;
	delete opt;

    oft=new subfactory;
	opt=oft->createOperator();
	cout<<"减法结果"<<opt->getresult(10,4)<<endl;

	delete oft;
	delete opt;

	return 0;
}

加法结果14
减法结果6

(3)抽象工厂模式
工厂类负责创建抽象产品的子类的实例。
抽象工厂模式的角色如下:
抽象工厂(Creator):它是抽象工厂模式的核心,包含对多个产品线的声明,任何工厂类都必须实现这个接口。

(1)具体工厂(Concrete Creator):具体工厂是抽象工厂的一个实现,负
(2)责实例化某个产品线中的产品对象
(3)抽象产品(Product):它是抽象工厂模式所创建的所有对象的父类,负责描述所有实例共有的接口
(4)具体产品(Concrete Product):它是抽象工厂模式所创建的具体对象。

#include <iostream>
#include<string>
using namespace std;

class clothes{
public:
	virtual void show()=0;
};

class s_jacket:public clothes{
public:
	void show(){
		cout<<"森马的夹克"<<endl;
	}
};

class s_jeans:public clothes{
public:
	void show(){
		cout<<"森马的牛仔裤"<<endl;
	}
};


class h_jacker:public clothes{
public:
	void show(){
		cout<<"海澜之家的夹克"<<endl;
	}
};

class h_jeans:public clothes{
public:
	void show(){
		cout<<"海澜之家的牛仔裤"<<endl;
	}
};

class absfactory{
public:
	virtual clothes*createjacket()=0;
	virtual clothes*createjeans()=0;
};
//森马工厂
class s_factory:public absfactory{
public:
	clothes* createjacket(){
		clothes *p=new s_jacket;
		return p;
	}
	clothes* createjeans(){
		clothes *p=new s_jeans;
		return p;
	}
};
//海澜之家工厂
class h_factory:public absfactory{
public:
	clothes* createjacket(){
		clothes *p=new h_jacker;
		return p;
	}
	clothes* createjeans(){
		clothes *p=new h_jeans;
		return p;
	}
};

void func(absfactory*abs){
	clothes* pjacket=abs->createjacket();
	clothes* pjeans=abs->createjeans();

	pjacket->show();
	pjeans->show();

	delete pjacket;
	delete pjeans;

}

int main(){
	absfactory* abs=new s_factory;
	func(abs);
	delete abs;
	abs=new h_factory;
	func(abs);
	delete abs;
	return 0;
}

森马的夹克
森马的牛仔裤
海澜之家的夹克
海澜之家的牛仔裤

(3)装饰模式

装饰(Decorator) 模式又称为包装模式,可以通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一一个替换方案。

装饰模式把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要使用对象时,客户端就可以有选择地、按顺序地使用装饰功能包装对象,动态地给一个对象添加些额外的功能。就增如功能来说,装饰模式比生成子类的方式更为灵活,在不改变接口的条件下。
(1)需要扩展一个类的功能,或给一个类增加附加功能时。

(2)需要动态地给一个对象增加功能,这些功能也可以动态地撤销。

(3)需要增加一些基本功能 的排列组合以产生更多的功能,使用继承变得不现实。
装饰者模式的角色组成如下:
(1)抽象构件角色(Component):给出一个抽象接口,以规范准备增加附加功能的对象。
(2)具体构件角色( Concrete Component):定义一个将要增加附加功能的类。
(3)装饰角色(Decorator):拥有一个构件(Component) 对象的实例,并定义一一个与抽象构件接口一致的接口。
(4)具体装饰角色(Concrete Decorator):负责给构件对象增加附加的功能。

#include <iostream>
#include<string>
using namespace std;
//饼的基类
class Cake{
public:
	virtual string getname()=0;
	virtual double getprice()=0;
protected:
	string name;
};
//手抓饼
class shreddedcake:public Cake{
public:
	shreddedcake(){
		name="手抓饼";
	}
	string getname(){
		return name;
	}
	double getprice(){
		return 5;
	}
};

//配料的基类
class condiment:public Cake{
protected:
	Cake* cake;
};


//加鸡蛋的饼
class egg:public condiment{
public:
	egg(Cake* cake){
		this->cake=cake;
	}
	string	getname(){
	return cake->getname()+"+鸡蛋";
	}
	double getprice(){
	return cake->getprice()+1.5;
	}
};

//加里脊的饼
class tenderloin:public condiment{
public:
	tenderloin(Cake* cake){
		this->cake=cake;
	}
	string	getname(){
	return cake->getname()+"+里脊";
	}
	double getprice(){
		return cake->getprice()+2;
	}
};v

int main(){
	shreddedcake* pc=new shreddedcake;
	cout<<pc->getname()<<" "<<pc->getprice()<<"元"<<endl;

	tenderloin* pst=new tenderloin(pc);
	cout<<pst->getname()<<" "<<pst->getprice()<<"元"<<endl;

	egg* pse=new egg(pst);
	cout<<pse->getname()<<" "<<pse->getprice()<<"元"<<endl;

	delete pse;
	delete pst;
	delete pc;
	return 0;
}

手抓饼 5元
手抓饼+里脊 7元
手抓饼+里脊+鸡蛋 8.5元

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值