c++ 模版2

本文详细探讨了C++中的类模板、函数模板、默认参数、类模板成员函数创建时机、继承、友元函数以及STL(标准模板库)的相关概念,包括容器、算法、迭代器等,通过实例演示了如何使用和理解这些高级特性。
摘要由CSDN通过智能技术生成

类模版与函数模版的区别

1.类模版使用只能用显式指定类型的方式
2.类模版中的模版参数列表可以有默认参数

#include<iostream>
using namespace std;


//template<class NameType,class AgeType>
template<class NameType, class AgeType = int>//类模版的模版参数列表里可以有默认参数
class Person {
public:
	Person(NameType name, AgeType age)
	{
		this->m_Name = name;
		this->m_age = age;
	}
	void showPerson() {
		cout << "name= " << this->m_Name <<"\t" << "age= " << this->m_age << endl;
	}
public:
	NameType m_Name;
	AgeType m_age;
};
void test01() {
	
	//Person p1("孙悟空", 999);   //错误,类模版无法进行自动类型推导
	Person<string, int>p1("孙悟空", 999);  //类模版只能使用显式指定类型方式
	p1.showPerson();
}
void test02() {
	Person<string>p2("猪八戒", 1);//当类模版的模版参数列表里有默认参数时,显示指定类型指定剩下那一个即可;
	p2.showPerson();
}
int main() {

	test01();
	test02();
}

类模版中的成员函数创建时机

#include<iostream>
using namespace std;

//首先创建2个类
class Person1{
public:
	void showPerson1() {
		cout << "Person1的调用" << endl;
	}
};
class Person2 {
public:
	void showPerson2() {
		cout << "Person2的调用" << endl;
	}
};

//创建一个类模版,类模版一致的数据类型为T;模版必须要确定T的数据类型,才可以使用;
template<class T>
class MyClass 
{
public:
	T obj;
	void func1() 
	{
		obj.showPerson1();
	}
	void func2()
	{
		obj.showPerson2();
	}
};
void test01() {
	MyClass<Person1>m;
	m.func1();
}
int main() {
	test01();
}

类模版对象做函数参数

通过类模版创建的对象,可以有三种方式向函数中进行传参,使用比较广泛的是第一种。
1.指定传入类型----直接显示对象的数据类型
2.参数模板化-------将对象中的参数变为模版进行传递
3.整个类模版化----将这个对象模板化进行传递

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

template<class NameType, class AgeType = int>
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		this->mName = name;
		this->mAge = age;
	}
	void showPerson()
	{
		cout << "name: " << this->mName << " age: " << this->mAge << endl;
	}
public:
	NameType mName;
	AgeType mAge;
};
//1、指定传入的类型
void printPerson1(Person<string, int>& p)
{
	p.showPerson();
}
void test01()
{
	Person <string, int >p("孙悟空", 100);
	printPerson1(p);
}

//2、参数模板化
template <class T1, class T2>
void printPerson2(Person<T1, T2>& p)
{
	p.showPerson();
	cout << "T1的类型为: " << typeid(T1).name() << endl;
	cout << "T2的类型为: " << typeid(T2).name() << endl;
}
void test02()
{
	Person <string, int >p("猪八戒", 90);
	printPerson2(p);
}
//3、整个类模板化
template<class T>
void printPerson3(T& p)
{
	cout << "T的类型为: " << typeid(T).name() << endl;
	p.showPerson();

}
void test03()
{
	Person <string, int >p("唐僧", 30);
	printPerson3(p);
}
int main() 
{
	test01();
	test02();
	test03();
}

类模版与继承

当类模板碰到继承时,需要注意一下几点:

  • 当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
  • 如果不指定,编译器无法给子类分配内存
  • 如果想灵活指定出父类中T的类型,子类也需变为类模板
#include<iostream>
using namespace std;
#include<string>

template<class T>
class Base {
public:
	T m;
};

class Son :public Base<int>//当子类继承的父类是一个类模版时,子类在声明的时候要指定父类中T的类型;
{

};

template<class T1,class T2> //也可以用T2指定父类中的T类型
class Son2 : public Base<T2>
{
public:
	Son2()
	{
		cout << "T1的类型是" << typeid(T1).name<< endl;
		cout << "T2的类型是 " << typeid(T2).name << endl;
	}
};
void test01() {
	Son s1;
}
void test02() {
	Son2<int,char>child1;
}
int main() {
	test01();
	test02();
}

类模版成员函数类外实现

类模版中成员函数类外实现时,需要加上模版参数列表

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

template<class T1,class T2>
class Person {
public:
	Person(T1 name, T2 age);
	void showPerson();
public:
	T1 m_Name;
	T2 m_Age;
};

//构造函数类外实现
template<class T1, class T2>
Person<T1,T2>::Person(T1 name, T2 age) {
	this->m_Name = name;
	this->m_Age = age;
}

//成员函数类外实现
template<class T1, class T2>
void Person<T1,T2>::showPerson() {
	cout << "姓名" << this->m_Name << "\t" << "年龄" << this->m_Age << endl;
}

void test01() {
	Person<string, int>p("Tom", 20);
	p.showPerson();
}

int main() {
	test01();
}

类模版分文件编写

问题:类模版中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
解决方法:
1、直接包含cpp源文件
2、将声明和实现写到同一个源文件中,并更改后缀名是.hpp,hpp是约定的名称,并不是强制
主流解决方式是第二种

person.hpp中代码:
#pragma once
#include <iostream>
using namespace std;
#include <string>

template<class T1, class T2>
class Person {
public:
	Person(T1 name, T2 age);
	void showPerson();
public:
	T1 m_Name;
	T2 m_Age;
};

//构造函数 类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {
	this->m_Name = name;
	this->m_Age = age;
}

//成员函数 类外实现
template<class T1, class T2>
void Person<T1, T2>::showPerson() {
	cout << "姓名: " << this->m_Name << " 年龄:" << this->m_Age << endl;
}

类模板分文件编写.cpp中代码

#include<iostream>
using namespace std;

将声明和实现写到一起,文件后缀名改为.hpp
#include "person.hpp"
void test01()
{
	Person<string, int> p("Tom", 10);
	p.showPerson();
}

int main() {
	test01();
}

类模版与友元

掌握类模版配合友元函数的类内类外实现
全局函数类内实现----直接在类内声明友元即可
全局函数类外实现----需要提前让编译器知道全局函数的存在

全局函数类内实现----直接在类内声明友元即可
#include<iostream>
using namespace std;
#include<string>

template<class T1,class T2>
class Person {
	//全局函数类内实现
	friend void printPerson(Person<T1, T2>& p) 
	{
		cout << "名字是" << p.m_Name << "\t" << "年龄是" << p.m_Age << endl;
	}
public:
	Person(T1 name, T2 age){ 
		this->m_Name = name;
		this->m_Age = age;
	}

private:
	T1 m_Name;
	T2 m_Age;
};

void test01() {
	Person<string,int> p1("Tom",20);
	printPerson(p1);//调用全局函数直接写函数名即可;
}

int main() {
	test01();
}

//全局函数的类外实现
#include<iostream>
using namespace std;
#include<string>

template<class T1,class T2>
class Person {
	friend void printPerson2<>(Person<T1, T2>& p); //加一个空模版的参数列表即可
public:
	Person(T1 name, T2 age){ 
		this->m_Name = name;
		this->m_Age = age;
	}

private:
	T1 m_Name;
	T2 m_Age;
};
//全局函数的类外实现
template<class T1, class T2>
void printPerson2(Person<T1, T2>& p) {
	cout << "名字是" << p.m_Name << "\t" << "年龄是" << p.m_Age << endl;
}
void test02() {
	Person<string,int> p2("Jerry",30);
	printPerson2(p2);
}

int main() {
	test02();
}

类模版案例–数组类封装的需求分析

class  MyArray
{
private:
	//数组  T * pAddress;
	//容量  a_Capacity;
	//大小  m_Size;
public:
构造函数(容量)
拷贝构造
operator = 
利用下标的方式访问数组中的元素  ?
尾插法
尾删法
获取数组容量
获取数组大小
析构
}

类模版案例–数组类封装(上)

类模版案例–数组类封装(下)

STL的诞生

1、c++面向对象的思想是封装、继承、多态;泛型编程思想是类模版和函数模版
封装就是把它的属性和行为抽象出来,作为一个整体,来实现这些事和物,提高了复用性;//封装简单理解为物以类聚;
继承就是子类继承父类,子类把父类的属性和行为继承下来,把它的属性和行为拿到手,不用再重新声明,提高了复用性;
多态就是一个函数名称可以有多个接口,由于对象不同,父类指针指向子类对象不同,对象创建的不同调用同一个接口会产生不同的形态;也是提高了复用性;
2、在大多数情况下,数据结构和算法都没有一套标准,导致被迫从事大量重复工作。
3、为了建立数据结构和算法的一套标准,诞生了STL

STL的基本概念

1、STL(standarad Template Library:标准模版库)
2、STL从广义上分为:容器(container)算法(algorithm)迭代器(iterator)
3、容器和算法之间通过迭代器进行无缝衔接
4、STL几乎所有的代码都采用了模版类或者模版函数

STL六大组件

STL大体分为六大组件,分别是:容器,算法,迭代器,仿函数,适配器(配接器),空间配置器

1、容器:各种数据结构,如vector,list,deque,set,map等,用来存放数据
2、算法:各种常用的算法,如sort、find、copy、for_each等
3、迭代器:扮演了容器与算法之间的胶合剂
4、仿函数:行为类似函数,可作为算法的某种策略
5、适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
6、空间配置器:负责空间的配置与管理

STL中容器、算法、迭代器

容器:置物之所也
STL容器就是将运用最广泛的一些数据结构实现出来
常用的数据结构:数组、链表、树、栈、队列、集合、映射表等
这些容器分为序列式容器和关联式容器两种:
序列式容器:强调值的排序,序列式容器中的每个元素均有固定的位置
关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系

算法:问题之解法也
有限的步骤,解决逻辑或数学上的问题,这一门学科称为算法。
算法分为质变算法和非质变算法
质变算法:是指运算过程中会更改区间内元素的内容,例如拷贝、替换、删除等等
非质变算法:是指运算中不会更改区间中的元素内容,例如查找、计数、遍历、寻找极值等等

迭代器:容器和算法之间粘合剂
提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。
每个容器都有自己专属的迭代器。
迭代器使用非常类似于指针,初学阶段我们可以先理解迭代器为指针。
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值