从零学习C++第八篇:类模板与向量

一、类模板

类模板一般声明方法如下:

template <类模板参数>class 类名{//实体}

类模板对象:类名<模板实例化参数类型>对象名(构造参数实参列表);

                    类名<模板实例化参数类型>对象名;

在类外面定义成员函数,必须用template重写类模板声明:

                template<模板参数>

                返回值类型 类名<模板类型参数>::成员函数名(函数参数列表){//函数体}

/*求最大值模板*/
#include <iostream>
using namespace std;
template <class T>
class Max4{
	T a,b,c,d;
	T Max(T a,T b){
		return (a>b)?a:b;
	}
public:
	Max4(T,T,T,T);   //构造函数
	T Max(void);     //比较四个对象大小
};
template <class T>   //定义成员函数 要再次申请模板
Max4<T>::Max4(T x1,T x2,T x3,T x4):a(x1),b(x2),c(x3),d(x4){}

template <class T>      //定义成员函数 要再次申请模板
T Max4<T>:: Max(void){          //要将Max4<T>看作一个整体
	return Max(Max(a,b),Max(c,d));
}

int main() {
	Max4<int>A(5.3,6.5,7.9,8.1);
	Max4<string>B("dsf","c","fsdfsdf","fdfd");
	cout<<A.Max()<<endl;
	cout<<B.Max()<<endl;
	return 0;
}

运行结果:

8
fsdfsdf
/*求四个对象的和*/
#include <iostream>
using namespace std;
template <class T,int size=4>
class Sum{
	T m[size];
public:
	Sum(T a,T b,T c,T d){
		m[0]=a;
		m[1]=b;
		m[2]=c;
		m[3]=d;
	}
	T S(){
		return m[0]+m[1]+m[2]+m[3];
	}
};
int main() {
	Sum<int,4>num1(6,9,8,2);
	Sum<string,4>str1("dsd","w","cv","cvb");
	cout<<num1.S()<<endl;
	cout<<str1.S()<<endl;
	return 0;
}

运行结果:

25
dsdwcvcvb

类模板的派生与继承

模板类继承非模板类

/*模板类Line继承非模板类Point*/
#include <iostream>
using namespace std;
class Point{               //定义非模板类
	int x,y;
public:
	Point(int a,int b):x(a),y(b){}
	void Display(){
		cout<<x<<","<<y<<endl;
	}
};

template <typename T>
class Line:public Point{    //Line公有继承Point
	T x2,y2;
public:
	Line(int a,int b,T c,T d):Point(a,b){   //构造函数
			x2=c;
			y2=d;
	}
	void display(){
		cout<<x2<<","<<y2<<endl;
	}

};

int main() {
	Point a1(3,8);
	a1.Display();
	Line<float>a2(9.6,5.1,6.3,7.9);//Line为模板类  初始化  不能改变 x y的数据类型
	a2.Display();
	a2.display();
	return 0;
}

运行结果:

3,8
9,5
6.3,7.9

模板类派生出一个模板类

/*设计一个模板类Point,然后公有派生一个模板类Line*/

#include <iostream>
using namespace std;
template <typename T>
class Point{
	T x,y;
public:
	Point(T a,T b){
		x=a;
		y=b;
	}
	void display(){
		cout<<x<<","<<y<<endl;
	}
};
template <typename T>
class Line:public Point<T>{   //公有继承模板
	T x2,y2;
public:
	Line(T a,T b,T c,T d):Point<T>(a,b){   //构造函数
		x2=c;
		y2=d;
	}
	void display(){
		Point<T>::display();//先调用Point类的display()方法
		cout<<x2<<","<<y2<<endl;
	}

};
int main() {
	Line<float> A(3.2,5.5,6.1,33);
	A.display();
	return 0;
}

运行结果:

3.2,5.5
6.1,33

二、向量

向量(vector)是一维数组的类模板,与数组相似,元素项是连续存储的,与数组不同的是,向量中存储元素的多少可以在运行中动态的增加或减少,长度不固定。

向量是类模板,具有成员函数。

向量的定义:

vector<type>name;  //定义type型向量空表

vector<type>name(length);  //定义具有length个type的向量,元素初始化为0

vector<type>name(length,a)  //定义具有length个type的向量,元素初始化为a

vector<type>name1(name)  //使用已定义的向量name构造向量name1

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

int main() {
	vector<int>A(3,5);//定义3个int型向量,其它元素均为5
	vector<int>B(A);//使A与B相同,有三个int型的向量,其他元素均为5
	vector<char>C;
	vector<char>D(2*2,'A');
	vector<char>E;
	E=D;
	cout<<A.size()<<","<<B.size()<<","<<C.size()<<","<<D.size()<<","<<E.size()<<endl;

	int IA[10]={1,5,8,45,63,21,56,54,65,96};//不能使用列表初始化一个向量,可以先初始化一个数组,然后定义
	vector<int>VB(IA,IA+10);              //不能用这种方法去初始化一个已经声明或定义的向量
	for(int i=0;i<VB.size();i++){
		cout<<VB[i]<<",";
	}
	
	
	return 0;
}

运行结果:

3,3,0,4,4
1,5,8,45,63,21,56,54,65,96,

泛型指针

正向泛型指针:

typedef vector<type>::iterator 泛型指针名;

逆向泛型指针:

typedef vector<type>::reverse_iterator 指针名;

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

int main() {
	vector<int>A(3,5);//定义3个int型向量,其它元素均为5
	vector<int>B(A);//使A与B相同,有三个int型的向量,其他元素均为5
	vector<char>C;
	vector<char>D(2*2,'A');
	vector<char>E;
	E=D;
//	cout<<A.size()<<","<<B.size()<<","<<C.size()<<","<<D.size()<<","<<E.size()<<endl;

	int IA[10]={1,5,8,45,63,21,56,54,65,96};//不能使用列表初始化一个向量,可以先初始化一个数组,然后定义
	vector<int>VA(IA,IA+10);              //不能用这种方法去初始化一个已经声明或定义的向量
//	for(int i=0;i<VA.size();i++){
//		cout<<VA[i]<<",";
//	}

	/*使用泛型指针和copy函数*/
	typedef vector<int>::iterator iterator;  //正向泛型指针
	typedef vector<int>::reverse_iterator reverse_iterator;  //逆向泛型指针

	iterator first=VA.begin();//定义正向泛型指针first,并指向向量的第一个元素位置
	for(first;first<VA.end();first++){  //end是最后一个向量后一个位置
		cout<<*first<<" ";
	}           //循环正向输出VA
	cout<<endl;
	copy(VA.begin(),VA.end(),ostream_iterator<int>(cout," "));  //整体正向输出VA
	//编译程序时出现如下错误error: ‘ostream_iterator’ was not declared in this scope
	//在头文件中加入iterator这个头文件  #include<iterator> 错误解决
	cout<<endl;
	reverse_iterator last=VA.rbegin(); //rbegin是最后一个向量的位置
	for(last;last<VA.rend();last++){  //rend是第一个元素 前一个的位置
		cout<<*last<<" ";
	}            //循环逆向输出VA
	cout<<endl;
	reverse_copy(VA.begin(),VA.end(),ostream_iterator<int>(cout," "));  //整体逆向输出VA
	cout<<endl;
	vector <int>VB(12);//长度为10  原样输出  ;小于10,崩溃;大于10,输出0
	copy(VA.begin(),VA.end(),VB.begin());//把VA复制给VB
	reverse_copy(VB.begin(),VB.end(),ostream_iterator<int>(cout," "));  //整体逆向输出VB
	cout<<endl;
	copy(VB.begin(),VB.end(),ostream_iterator<int>(cout," "));  //整体正向输出VA
	return 0;
}

运行结果:

1 5 8 45 63 21 56 54 65 96 
1 5 8 45 63 21 56 54 65 96 
96 65 54 56 21 63 45 8 5 1 
96 65 54 56 21 63 45 8 5 1 
0 0 96 65 54 56 21 63 45 8 5 1 
1 5 8 45 63 21 56 54 65 96 0 0 
/*复数和结构作为向量元素的例子*/

#include <iostream>
#include<complex>
#include<vector>
using namespace std;
struct st{
	int a,b;

}a[]={{2,5},{4,8}};
int main() {
	complex<float>num[]={complex<float>(2,3),complex<float>(3.6,5.4)};//定义一个复数 数组
	vector<complex<float>*>vnum(2); //以复数 float型指针作为向量参数
	vnum[0]=&num[0];//赋值
	vnum[1]=&num[1];
	for(int i=0;i<2;i++){
		cout<<"real:"<<vnum[i]->real()<<" imag:"<<vnum[i]->imag()<<endl;
	}

	vector<st *>cp(2);//以st的指针作为向量cp的参数
	cp[0]=&a[0];
	cp[1]=&a[1];
	for(int i=0;i<2;i++){
			cout<<"a:"<<cp[i]->a<<" b:"<<cp[i]->b<<endl;
		}
	return 0;
}

运行结果:

real:2 imag:3
real:3.6 imag:5.4
a:2 b:5
a:4 b:8

向量的操作方法

1.访问向量容量信息

size():当前存放的信息个数。

capacity():返回无需再次分配就能容纳的对象个数。

max_size():返回对象最多可以容纳的个数       max_size()>capacity()>size()

empty();若为空 返回ture  不为空 返回0

2.访问向量中对象

front():返回向量中第一个对象。

back():返回向量中的最后一个对象

operator[ ](size_type,n):返回向量中第n+1个对象

3.插入

push_back(const T&):在尾部插入

insert(inerator it,const T&):向泛型指针ti所指的位置前插入

insert(inerator it,size_type n,const T&x):向泛型指针ti所指的位置前插入n个值为x的对象

4.删除

pop_back(const T&):删除向量中最后一个对象

erase(inerator it):删除泛型指针it所指向的容器对象

clrae():删除向量中所有对象,

#include <iostream>
#include<vector>
#include<algorithm>
#include<functional>
#include<iterator>
using namespace std;

int main() {
	char st[11]="abcdefghij";
	vector<char>a(st,st+10),b(8);
	cout<<a.size()<<" "<<a.max_size()<<" "<<a.empty()<<endl; //10 4294967295 0
	for(int i=0;i<a.size();i++){
		cout<<a[i]<<" ";
	}                          //a b c d e f g h i j
	cout<<endl;
	for(char j='a',i=0;i<b.size();i++){
			b[i]=j+i;
		}
	for(int i=0;i<b.size();i++){
			cout<<b[i]<<" ";
		}                        //a b c d e f g h
	cout<<endl;
	cout<<a.front()<<" "<<b.back()<<" "<<a.operator [](2)<<endl;//返回向量中的第一个、最后一个、第2+1个元素对象 a h c

	a.pop_back();//删除最后一个元素
	a.push_back('z');//在最后插入z    若插入za  只能输出a
	copy(a.begin(),a.end(),ostream_iterator<char>(cout," "));  //整体正向输出a
	cout<<endl;
	vector<char>::iterator p;
	p=a.begin();//泛型指针p指向向量a的第一个元素
	a.insert(p+3, 'A');//a[3]='A'
	copy(a.begin(),a.end(),ostream_iterator<char>(cout," "));  //整体正向输出a
	cout<<endl;

	p=a.end();//一定要给p一个位置
	a.insert(p, 3, 'K');
	copy(a.begin(),a.end(),ostream_iterator<char>(cout," "));  //整体正向输出a
	cout<<endl;
	cout<<a.size()<<" "<<a.capacity()<<endl;

	p=a.begin();
	a.erase(p+1);  //删除b
	copy(a.begin(),a.end(),ostream_iterator<char>(cout," "));  //整体正向输出a
	cout<<endl;

	a.clear();
	cout<<a.empty();
	return 0;
}

运行结果:

10 4294967295 0
a b c d e f g h i j 
a b c d e f g h 
a h c
a b c d e f g h i z 
a b c A d e f g h i z 
a b c A d e f g h i z K K K 
14 20
a c A d e f g h i z K K K 
1

出圈游戏:

依次输出出列人的名字

#include <iostream>
#include<vector>
#include <string.h>
#include <stdio.h>
using namespace std;
class SeqList{
	char name[10];
public:
	void DispName(){
		cout<<name;
	}
	void SetName(char b[]){
		strcpy(name,b);//strcpy() 复制字符串的库函数
	}
	void Joseph(vector<SeqList>&);
};
void SeqList::Joseph(vector<SeqList>&c){
	int m,star,i,j,k;
	cout<<"输入间隔数m(m<=20):"<<endl;
	cin>>m;
	if(m>20){
		cout<<"m>20,请重新输入"<<endl;
		cin>>m;
	}
	cout<<"从第几个人开始报数(不能大于"<<c.size()<<")"<<endl;
	cin>>star;
	if(star>c.size()){
		cout<<"m>"<<c.size()<<",请重新输入"<<endl;
		cin>>star;
	}
	cout<<"输入名字"<<endl;
	getchar();
	char s[10];
	for(int i=0;i<c.size();i++){
		cout<<"输入第"<<i+1<<"个人的名字:"<<endl;
		gets(s);
		c[i].SetName(s);
	}
	i=star-2;
	vector<SeqList>::iterator p;
	p=c.begin();
	int length=c.size();
	for(int k=0;k<=length;k++){
		j=0;
		while(j<m){
			i++;
			if(i==c.size()){
				i=0;
			}
			j++;
		}
		if(k==length){
			break;
		}
		c[i].DispName();
		cout<<",";
		c.erase(p+i);
		--i;
	}
	c[i].DispName();
	cout<<endl;

}
int main() {
	int length=0;
	cout<<"输入人数:";
	cin>>length;
	vector<SeqList>c(length);
	SeqList game;
	game.Joseph(c);
	return 0;
}

运行结果:

输入人数:6
输入间隔数m(m<=20):
12
从第几个人开始报数(不能大于6)
2
输入名字
输入第1个人的名字:
张三
输入第2个人的名字:
李四
输入第3个人的名字:
王五
输入第4个人的名字:
赵六
输入第5个人的名字:
刘七
输入第6个人的名字:
朱八
张三,王五,李四,朱八,刘七,赵六,



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值